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::fun
son::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++:包含父类时出现多重定义错误?的主要内容,如果未能解决你的问题,请参考以下文章