我是C ++的新手。我对C ++中的多个定义错误有些怀疑。
假设我在一个程序中有3个文件。一个头文件和两个.cpp文件。我已将头文件包含在.cpp文件中。
我们可以通过在头文件中使用extern
并仅在其中一个文件中定义类来解决此问题吗?如果我们可以使用此方法解决问题,我们是否必须包含.cpp(与类定义)到其他.cpp文件(没有类定义)?
我在头文件中声明并定义了一个类。这种情况是否与上述相同(在1中提到)?
我在头文件中声明了一个类,我在每个.cpp文件中定义了类,但定义(函数体)不同。那么这种类型的实现会导致多个定义错误吗?如果是这样,我们如何解决.cpp文件中函数体不同的问题?
答案 0 :(得分:8)
1)您可以通过仅在一个cpp文件中“定义类”来解决此问题。你为什么要在两个文件中定义它?
2)不要在头文件中定义东西,只声明它们。此规则有例外,例如内联函数。类本身也可以定义多次(我的意思是声明类的方法和数据成员,(即写class XYZ { ... };
)但每个定义必须相同。实现这一点的最简单方法是定义一个类一旦在头文件中。然后在多个地方包含该头文件而得到的每个定义必然是相同的。
3)这个甚至更愚蠢,两次定义一些东西是一回事,但是定义两次并且不同地每次定义更不合理。
我想这个问题就是为什么你认为有时可能需要不止一次定义东西。不要那样做。
您还应该明确“定义班级”的含义。我认为这意味着定义类的方法和静态成员。但如果你有其他想法可能会引起混乱。像往常一样,避免这种术语混淆的最好方法是发布一些代码。
答案 1 :(得分:4)
要回答所有这些问题,您只需要查看声明和定义的目的。
类的声明只是声明该类存在以及在哪个上下文中。对于一个类,一个简单的前向声明(例如class Banana;
)允许你使用指向该类的指针或引用,但就是这样。
定义确切地说明了类是什么。也就是说,它拥有哪些成员以及派生的基类。无论何时访问类的成员,或者需要知道其实例的大小,都需要它。这意味着需要将类定义放在头文件中,以便它可以包含在使用该类的所有文件中的任何位置。这没关系,因为标准说只要所有定义都相同,就可以在多个翻译单元中定义一个类。
类定义通常如下所示:
class Banana
{
public:
Banana(){}
void eat();
private:
//....
};
但是,请注意,此类定义仅表示类本身的定义,而不是非内联成员函数。例如上例中的void eat()
。这些需要在.cpp文件中定义,因为它们可能无法在多个翻译单元中定义。
简而言之:
答案 2 :(得分:1)
1)您的项目中不能有两个相同类的定义。我不知道你打算如何使用它。如果要创建具有不同行为的一个类的实例,请使用虚函数,如:
class A {
public:
virtual int foo() = 0;
}
class B : public A {
public:
virtual int foo() { return 1; }
}
class C : public A {
public:
virtual int foo() { return 2; }
}
2)您可以在头文件(java风格)中定义类,但这不是最好的主意,因为编译器将消耗更多资源来构建其他文件,包括此标头。让编译器快速工作 - 在.cpp文件中定义类。
3)见第1页
答案 3 :(得分:1)
在几个地方定义一个类没有问题。当您将定义放在标题中并且#include
标题放在多个源文件中时,就会发生这种情况。但是,请注意,定义类意味着写出类包含的内容,而不是定义其成员。这是一个类定义:
class C {
void f(); // member function declaration
void g() { } // member function declaration with inline definition
int i; // member declaration
static int j; // member declaration
};
与大多数事情一样,您无法在单个源文件中多次定义它。但是,它可以出现在任意数量的源文件中,只要它在任何地方都是相同的。
此类定义声明必须在某处定义的两个成员,通常如下所示:
void C::f() {
std::cout << "In C::f\n";
}
int C::j = 3;
这些定义在整个程序中只出现一次;通常每个都在源文件中定义一次。