C++:包含父类时出现多定义错误

C++: Multiple definition error when including parent class?

本文关键字:定义 错误 包含 父类 C++      更新时间:2023-10-16

我正在用派生类编写一个简单的银行程序,在包含父类时遇到Multiple definition of <method name>错误。

请记住,我昨天刚开始用C++编写代码,从Java/PHP过渡到处理头/定义对我来说有点困惑。请纠正您发现的任何错误!

以下是我的文件/代码示例:

文件

  • 帐户.h
  • Account.cpp(超级)
  • 支票帐户.cpp(子项)
  • SavingsAccount.cpp(儿童)

当将父类(Account.cpp)包含到任何文件中时,都可以重现错误。我已经将代码减少了很多,但它应该让您了解我是如何处理继承的。

需要说明的是,当我#include时,任何文件的子类(ChequingAccount.cpp)都可以正常工作,继承的函数也可以正常工作。但是,当我#include时,父类(Account.cpp)会中断编译器,所有方法都会出现Multiple definition of <method name>错误。

同样,我不确定这是否是正确的方法,但这是我从教程中了解到的。

代码

账户.h

#ifndef ACCOUNT_H
#define ACCOUNT_H
class Account
{
    protected:
        double m_balance;
    public:
        Account(double balance); // Constructor.
        virtual ~Account(); // Destructor.
        // Accessor Methods.
        double getBalance() const;
        // Mutator Methods.
        virtual void withdrawFunds(double amount);
        void depositFunds(double amount);
};
#endif

Account.cpp(超类)

#include "Account.h"
Account::Account(double balance = 0)
{
    m_balance = balance;
}
Account::~Account()
{
    // TODO: Delete this data structure...
}
double Account::getBalance() const
{
    return m_balance;
}
void Account::withdrawFunds(double amount)
{
    m_balance -= amount;
}
void Account::depositFunds(double amount)
{
    m_balance += amount;
}

支票账户.cpp(儿童)

#include "Account.h"
class ChequingAccount: public Account
{
    public:
        ChequingAccount(int id, int userId, double balance) : Account(id, balance){};
        void withdrawFunds(double amount)
        {
            // Override parent method.
        }
};

如有任何帮助,我们将不胜感激!非常感谢。

当您#包含"some file.cpp"时,您正在指示编译器将该cpp文件的内容复制到程序中的该点。这将创建"some file"的两个编译版本,这将导致"Multiple Definitions"。

首先,在基类和子类中声明的"相同"函数不会导致多重定义错误。

这里只有一个例子和解释,旨在帮助你理解我的观点:

main.cpp

class father{
    void fun();
}
void father::fun(){}
class son : public father{
    void fun();
}
void son::fun(){}
int main()
{
    return 0;
}

你编译它,肯定没有多重定义错误。在Java中,我们在类中定义函数。在C++中,只有内联函数在类中定义,其他函数是声明,可以在任何时候声明。参见定义语法:father::fun son::fun。它们实际上定义了两个不同的函数,一个在father中,另一个在son中。因此不存在多重定义错误。再一次,在类声明中,您只能定义内联函数,也只能声明非内联函数。因此,存在多个定义错误。这只是为了帮助你以语法的方式理解它。

顺便说一句,如果编译器未能内联,也不会出现多重定义错误,因为即使您在头文件中定义内联函数并将文件包含在任何位置,内联函数也是内部链接的。

我编译了你的代码,并在你定义的构造函数中得到了不同的错误。无论如何,使用"include"包含cpp文件意味着您不了解实现文件和接口文件的要点。

您还需要在child的.cpp文件中显式地将child的方法声明为子类的成员。见下文:

支票账户.cpp(儿童)

#include "Account.h"
class ChequingAccount: public Account
{
    public:
        ChequingAccount(int id, int userId, double balance) : Account(id, balance){};
        void ChequingAccount::withdrawFunds(double amount)
        {
            // Override parent method.
        }
};

在定义void ChequingAccount::withdrawFunds(double)时,您已经定义了void Account::withdrawFunds(double)

尝试virtual void ChequingAccount::withdrawFunds(double)

virtual关键字类似于Java中的override。

简而言之,不应该包含cpp文件。

出现多重定义错误的原因实际上与类继承无关。

考虑一个简单的例子:

add.h:

#ifndef __ADD_H_
#define __ADD_H_
int add(int a);
#endif

add.cpp:

#include "add.h"
int add(int a) { return a + 1; }

main.cpp:

#include "add.h"
int main() { return add(-1); }

C++处理#include指令的方法只是复制粘贴包含的文件并替换#include行。因此,如果我们手动扩展上述文件,我们将得到以下内容:

add.cpp:

#ifndef __ADD_H_
#define __ADD_H_
int add(int a);
#endif
int add(int a) { return a + 1; }

main.cpp:

#ifndef __ADD_H_
#define __ADD_H_
int add(int a);
#endif
int main() { return add(-1); }

这会很好用的。(我们可以对一个函数进行多次声明)

但是,如果您决定包含.cpp文件而不是.h文件,如以下代码所示:

main.cpp:

#include "add.cpp" // notice here
int main() { return add(-1); }

如果你像我们刚才那样扩展它:

add.cpp:

#ifndef __ADD_H_
#define __ADD_H_
int add(int a);
#endif
int add(int a) { return a + 1; }

main.cpp:

#ifndef __ADD_H_
#define __ADD_H_
int add(int a);
#endif
int add(int a) { return a + 1; }
int main() { return add(-1); }

您将看到该代码包含函数add的多个定义,其中一个在add.cpp中,另一个在main.cpp中。当将这两个文件链接在一起时(每个.cpp文件都是使用编译器单独编译的,然后使用链接器链接在一起),链接器会被add的两个定义弄糊涂,不知道该使用哪一个,所以它会开始抱怨。