3

我有以下课程:

//myClass.h

myClass{
    int data;
public:
    myClass();
    void foo1(int);
    void foo2();
    ~myClass();
};

//myClass.cpp

#include"myClass.h"
myClass::foo1(int a){
    data = a ;
}

// main
int main(){
    myClass m;
    m.foo1(10);
}

为什么我们可以有一个未实现的函数(即头文件中的函数原型,但.cpp 文件中没有定义),但不能有一个未实现的默认构造函数或析构函数?

如果我未实现默认构造函数/析构函数(如上面的示例),为什么会出现编译器错误?

undefined reference to myClass::myClass()当我没有实现构造函数时,我看到了一个undefined reference to vtable for myClass,当我没有实现析构函数时,我看到了一个。但是,如果我实现了这两个(即使是空的块{}),并且没有实现一个方法(例如foo2()),编译器不会抱怨。

构造函数/析构函数本质上不只是类中的方法吗?如果是这样,为什么我可以有一个未定义的方法foo2(),但没有未定义的构造函数或析构函数?

如果有人可以帮助我理解这一点(而不仅仅是“因为它就是这样”:),那将不胜感激。

4

4 回答 4

4

如果是这样,为什么我可以有一个未定义的方法foo2(),但没有未定义的构造函数或析构函数?

因为您使用的是构造函数和析构函数,而不是使用foo2(). 添加对它的调用,您将收到链接时错误。

于 2013-10-18T14:52:09.003 回答
3

为什么我们可以有一个未实现的函数(即头文件中的函数原型,但.cpp 文件中没有定义),但不能有一个未实现的默认构造函数或析构函数?

你的断言是错误的。您可以有一个未实现的默认构造函数。事实上,这是确保您的类永远不会被隐式构造的一种方法。

如果我未实现默认构造函数/析构函数(如上面的示例),为什么会出现编译器错误?

因为您在代码中的某处使用它。重新阅读您的编译器错误。它可能会告诉您确切的位置。

这里是:

int main(){
myClass m;
m.foo1(10);

该行使用默认构造函数myClass m;实例化。myClass

如果不使用默认构造函数,则可以声明但不实现默认构造函数并编译干净。考虑:

class Foo 
{
public:
    Foo (int x) {}
    Foo();
};

int main()
{
    Foo f (1);
}

这里有一个声明Foo(),但没有实现。代码编译时没有编译器或链接器错误。但是,此代码不会编译干净:

int main()
{
    Foo f;
}

后一个例子是你想要做的,在这里:

myClass m;
于 2013-10-18T14:54:09.410 回答
1

编译器只关心你声明的代码(这是你的类声明所做的)。如果你声明你的构造函数,它假定你已经在某个地方实现了它。链接器将在您使用它时尝试找到该实现。对于构造函数/析构函数,您在尝试创建类的实例时使用它。如果它们不存在,您将收到链接器错误。如果您不使用foo2(),并且您不实现,则链接器不需要找到它,因此它不会尝试。因此,您不会收到链接器错误,并且您的代码将被成功编译并链接到可执行文件中。

于 2013-10-18T14:55:32.657 回答
0

为什么我们可以有一个未实现的函数(即头文件中的函数原型,但.cpp 文件中没有定义),但不能有一个未实现的默认构造函数或析构函数?

必须定义任何使用的函数。如果不使用,大多数函数可以保持未定义。

如果我未实现默认构造函数/析构函数(如上面的示例),为什么会出现编译器错误?

因为你的程序创建和销毁了你的类的一个实例,它使用了构造函数和析构函数;因为它们被使用,所以它们必须被定义。你已经声明了它们,所以它们不会被隐式定义;因此,您必须自己定义它们。

当我不实现构造函数时,我看到对 myClass::myClass() 的未定义引用;

那是因为构造函数用于创建对象。

vtable当我不实现析构函数时,对 myClass的未定义引用。

这是因为此编译器vtable在与析构函数相同的翻译单元中生成 (如果它既不是隐式的也不是内联的)。如果你不声明析构函数但不定义它,你也不会得到vtable

但是,如果我实现了这两个(即使使用空块 {}),并且未实现方法(例如 foo2()),编译器不会抱怨。

那是因为您不使用该功能。如果你要调用它,那么你会得到一个错误。

构造函数/析构函数本质上不只是类中的方法吗?

或多或少,是的;但它们在各个方面都很特别。语言规范将它们描述为“特殊成员函数”,并有一整章描述它们的属性。

如果是这样,为什么我可以有一个未定义的方法foo2(),但没有未定义的构造函数或析构函数?

重申:你必须定义你使用的任何东西。如果实例化类,则使用构造函数和析构函数。

于 2013-10-18T15:06:15.787 回答