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

Posted

技术标签:

【中文标题】C++:包含父类时出现多重定义错误?【英文标题】:C++: Multiple definition error when including parent class? 【发布时间】:2014-09-10 00:58:40 【问题描述】:

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

请记住,我昨天刚开始使用 C++ 进行编码,并且从 Java/php 开始,处理标头/定义对我来说有点混乱。请纠正您看到的任何错误!

这是我的文件/代码示例:

文件

Account.h Account.cpp(超级) ChequingAccount.cpp(儿童) SavingsAccount.cpp(儿童)

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

澄清一下,当我 #include 任何文件 (ChequingAccount.cpp) 的子类工作正常时,继承的函数按预期工作。但是,当我 #include 父类 (Account.cpp) 中断编译器时,所有方法都会出现 Multiple definition of <method name> 错误。

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

代码

Account.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;

ChequingAccount.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.
        
;

任何帮助将不胜感激!谢谢!

【问题讨论】:

当您说“将父类 (Account.cpp) 包含到任何文件中”时,究竟是什么意思。?如果你的意思是你做#include "Account.cpp",那么这可能就是问题所在。 @uesp 是的,就是这样。这样做有什么问题?我不打算使用父类,但我想知道为什么包含该文件时会出错?这更像是一个“为什么”的问题,而不是“我该如何解决这个问题”。 @user3745117 你真的这样做了吗?发布的代码显示了#include 的正确用法,以及.h 头文件。 @Potatoswatter 不,我的代码中没有这个,但我想知道为什么在我执行#include 时会出错。 【参考方案1】:

当您#include "some file.cpp" 时,您指示编译器将该 cpp 文件的内容复制到程序中的该点。这将创建您的“某些文件”的两个编译版本,这将导致“多个定义”。

【讨论】:

【参考方案2】:

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

这里只是一个示例和解释,旨在帮助您理解我的观点:

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::funson::fun。这些实际上定义了两个不同的函数,一个在father,另一个在son。所以没有多重定义错误。再一次,在类声明中你只能定义内联函数并且只能声明非内联函数。所以根本就存在多个定义错误。这只是为了帮助您以语法方式理解它。

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

我编译了您的代码,并在您定义的构造函数方面遇到了不同的错误。无论如何,包括使用"include" 的cpp 文件意味着您没有得到实现文件和接口文件的意义。

【讨论】:

【参考方案3】:

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

ChequingAccount.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.
        
;

【讨论】:

【参考方案4】:

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

试试virtual void ChequingAccount::withdrawFunds(double)

virtual 关键字类似于 Java 中的覆盖。

【讨论】:

这不是真的。它与 Java 不同,不会导致多重定义错误。请设计一个这样的案例并自己尝试。实际上,这两个函数在不同的命名空间中,因为类也是命名空间。【参考方案5】:

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

你得到一个多重定义错误的原因实际上与类继承无关。

考虑一个简单的例子:

添加.h:

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

添加.cpp:

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

main.cpp:

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

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

添加.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); 

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

添加.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的两个定义混淆,不知道使用哪一个,所以它会开始抱怨。

【讨论】:

以上是关于C++:包含父类时出现多重定义错误?的主要内容,如果未能解决你的问题,请参考以下文章

C++中两个文件读取一个.h时多个多重定义错误

多重通知:调用函数时出现未定义的变量错误[重复]

与 DLL 链接时出现“‘atexit’的多重定义”

包含自定义404错误页面时出现.htaccess问题

链接我的库的错误的多重定义

C++找到一个或多个多重定义的符号