对C++类的用法感到困惑
Confused about C++ class usage
下面的代码让我对类的用法有点困惑。
template <int dim>
class FEM
{
public:
FEM (unsigned int order,unsigned int problem);
~FEM();
...
FESystem<dim> fe;
DoFHandler<dim> dof_handler;
...
}
template <int dim>
FEM<dim>::FEM(unsigned int order,unsigned int problem)
:
fe (FE_Q<dim>(order), dim),
dof_handler (triangulation)
{
...
}
这里的"FESystem"、"DoFHandler"answers"FE_Q"是头文件中的一些预定义类。我对这个代码有几个问题:
(1) 为什么构造函数"fe"answers"dof_handler"在类"fe"本身之外声明,它们是否可能在第一个括号内声明,即在"fe"类定义内?
(2) 代码中的双冒号和冒号":"answers""分别有什么含义?为什么在这里使用它们?冒号":"是指继承吗?
template <int dim>
FEM<dim>::FEM(unsigned int order,unsigned int problem)
:
fe (FE_Q<dim>(order), dim),
dof_handler (triangulation){...}
我是C++新手。有人能帮我吗?非常感谢!
(1) 为什么构造函数"fe"answers"dof_handler"在类"fe"本身之外声明,它们是否可能在第一个括号内声明,即在"fe"类定义内?
是的,对于模板化类,它们可以在"FE"模板类定义的内部或外部。有些人更喜欢将它们放在外部以便于阅读,在那里他们可以看到所有可用函数的列表,而不必向下滚动太远。
但是,对于常规的非模板类,请将类外实现放在相应的源(.cpp
)文件中,而不是放在类下面或类中。原因是,包含您的头的其他所有类都将一遍又一遍地编译相同的实现,这将减慢您的构建速度,并生成巨大的二进制文件。对于模板化类,您别无选择。它们必须由每个翻译单元编译,因为模板化的代码将由编译器生成。
(2) 代码中的双冒号和冒号"::"answers":"分别有什么含义?为什么在这里使用它们?冒号":"是指继承吗?
双冒号是你的范围。它可以是名称空间或类名。这使得两个不同类中的两个函数名称完全相同而不会发生名称冲突成为可能。它对于覆盖非常有用。
例如,您可以在标题中包含以下内容:
class A
{
public:
virtual foo(int a);
};
class B : public A
{
public:
virtual foo(int a);
};
并将其保存在您的源文件(.cpp
)中:
A::foo(int a) {
printf("Hello World from A::foo(%s)n", a);
}
B::foo(int a) {
A::foo(a); // calling the super class's foo(int)
printf("Hello World from B::foo(%s)n", a);
}
如果我们没有范围,我们就无法区分这两个函数。在Java或C#中,它被简化为一个单点。
在这种特殊情况下,单个冒号是C++构造函数的一个非常特殊的特性。只有构造函数才能执行此操作。这被称为"初始值设定项",它们是一个巧妙的小优化,可以用来为成员变量设置默认值,比在构造的函数范围内手动设置更快。
例如,如果您在这里有这样的类:
class A
{
public:
A(); // constructor
int a;
float b;
};
您可能会想在.cpp
源文件中这样编写构造函数:
A::A() {
a = 0;
b = 0.0;
}
但相反,通过初始化,您可以这样写:
A::A() :
a(0),
b(0.0)
{
}
只要你按照与它们在头中声明的顺序相同的顺序初始化它们,它们就可以更快地初始化你的内存。在这个特定的示例中,如果在a
之前初始化b
,则优化将不起作用。
C++一开始可能很难理解,但它是一种非常强大的语言,学习起来非常有趣。
双冒号用于指定您正在为特定类实现函数。在这种情况下,它是FEM类构造函数的实现。如果FEM有一个方法DoIt(),那么实现可能看起来像:
template<int dim>
int FEM<dim>::DoIt() { return 1; }
如果要将参数直接传递到成员变量的构造函数中,则可以将单个冒号":"与构造函数一起使用。因此,在上面的代码中,FEM的构造函数将参数传递给它的成员fe
。FESystem必须具有一个构造函数,该构造函数接受FE_Q<lt;dim>>和一个int作为参数。它还将一些内容传递给DoFHandler,但不清楚代码中的triangulation
是什么。这看起来不像是要编译的。
方法的实际实现通常保存在一个单独的文件中。因此,类名和它前面的双冒号用于标识它们所属的类。
头文件中的源代码将与使用这些类定义的每一段代码一起编译。这些方法背后的实际程序可以单独编译,并在链接阶段添加。
- 这个指针在c++中的用法
- 当C++中需要自动删除时,这是静态的正确用法吗?
- libstdc++ 文件系统中未初始化的用法?
- 复制和交换习惯用法与移动操作之间的交互
- 类作用域的类型别名"using":[何时]方法中的用法可以先于类型别名?
- 命名参数习惯用法和(抽象)基类
- 省略号在C++中的所有用法
- () 在 C++ 11 中的特殊而奇怪的用法?
- 构造函数的用法
- 模板类中自动的类用法不完整
- 这里的 = 运算符有什么用法?
- 什么模板用法在阶乘中更好
- 如果可变长度元素的constexpr用法得到<>
- 为什么 setjmp/longjmp 的这种用法是未定义的行为?
- 访问提升:shared_ptr 主范围外崩溃,断言失败:px != 0.指针的正确用法是什么?
- C++ 中函数中 Const 用法之间的差异
- equal_to模板类C++用法
- PCL 中的 GICP 用法
- 向量的正确用法<int>::size_type
- C++命名空间的基本用法