C++ 继承、纯虚函数和非内联成员函数定义

C++ 继承、纯虚函数和非内联成员函数定义,c++,inheritance,unresolved-external,pure-virtual,C++,Inheritance,Unresolved External,Pure Virtual,我已将我的问题归结为一个*.cpp文件中的以下代码: class A { public: A() {}; int PerformAction() { return Action(); } protected: virtual int Action(); } class B: public A { protected: int Action(); } int B::Action() { return 4; } int main

我已将我的问题归结为一个*.cpp文件中的以下代码:

class A {
public:
    A() {};

    int PerformAction() {
        return Action();
    }

protected:
    virtual int Action();
}

class B: public A {
protected:
    int Action();
}

int B::Action() {
   return 4;
}

int main() {
    B newB;
    newB.PerformAction();
};
前面的代码在B::Action()上抛出一个未解决的外部符号错误。。将
a::Action()
的定义更改为:

virtual int Action() = 0;
相反,当在主函数中使用抽象类时,
无法实例化抽象类
编译器错误。我看到的所有答案都与代码跨多个文件传播有关,但这都发生在一个源文件中。我猜想这与
B
Action()
的实现有关,它不在
B
的类定义之内,但看不出它会导致任何错误的原因

前面的代码在
B::Action()
上抛出未解析的外部符号错误

实际上,必须定义所有非纯虚拟函数,以便将它们的地址存储在类的虚拟函数表中

而是产生无法实例化抽象类编译器错误

不,它没有:

如果您试图直接实例化
A
,或未重写纯虚函数的子类,则会出现该错误<代码>B会覆盖它,因此不是抽象的

可能,您的实际类
B
操作的签名不正确,因此它实际上不会覆盖
A
中声明的签名。在C++11中,您可以将
override
说明符添加到
B
中的说明符中,以获得在这种情况下更有用的错误消息

我想这与
B
Action()的实现有关
B

不,这不应该是个问题,只要函数只有一个定义

前面的代码在
B::Action()
上抛出未解析的外部符号错误

实际上,必须定义所有非纯虚拟函数,以便将它们的地址存储在类的虚拟函数表中

而是产生无法实例化抽象类编译器错误

不,它没有:

如果您试图直接实例化
A
,或未重写纯虚函数的子类,则会出现该错误<代码>B
会覆盖它,因此不是抽象的

可能,您的实际类
B
操作的签名不正确,因此它实际上不会覆盖
A
中声明的签名。在C++11中,您可以将
override
说明符添加到
B
中的说明符中,以获得在这种情况下更有用的错误消息

我想这与
B
Action()的实现有关
B


不,只要函数只有一个定义,这就不应该是问题。

您的错误消息加在一起,表明
a::Action
B::Action
之间的签名不匹配,因此
B::Action
不会成为重写器。签名必须完全匹配(包括
this
)的cv限定,但允许返回类型协方差

B::Action
必须是
虚拟的
。如果签名匹配,则它将隐式显示,除非它是模板。模板无法覆盖


如果您有C++11编译器,我建议使用
override
关键字将签名不匹配设置为编译错误。

您的错误消息加在一起,表明
a::Action
B::Action
之间存在签名不匹配,因此
B::Action
不会成为重写器。签名必须完全匹配(包括
的cv限定),但允许返回类型协方差

B::Action
必须是
虚拟的
。如果签名匹配,则它将隐式显示,除非它是模板。模板无法覆盖


如果您有C++11编译器,我建议使用
override
关键字,将签名不匹配设置为编译错误。

这显然不是您正在编译的代码-缺少分号并尝试调用受保护的函数将在您报告的链接器错误之前给出编译器错误。一旦我修复了这些错误,并使函数如您所描述的那样纯虚拟,就不会有错误:另外,请不要在发布的代码中添加行号;为了测试它,必须删除它们是一件痛苦的事情。而且,
main
必须返回
int
。为了理解为什么会出现错误,我们需要显示错误的代码。此代码有不同的错误(缺少分号,以及
main
的错误类型),并且在修复这些错误后可以干净地编译。没有办法知道您的代码可能出了什么问题。大概它在做一些尝试实例化
A
的事情,但除此之外,我无法猜测。因此,请将其简化为显示相同错误的代码。上面的代码甚至没有显示您声称的错误。至少,尝试编译/链接/运行您发布的代码,并报告实际代码中的错误,而不是您没有向我们展示的其他代码。这显然不是您正在编译的代码-缺少分号和尝试调用受保护函数将在您报告链接器错误之前给出编译器错误。一旦我修复了这些错误,并使函数如您所描述的那样纯虚拟,就不会有错误:另外,请不要在发布的代码中添加行号;为了测试它,必须删除它们是一件痛苦的事情。而且,
main
必须返回
int
。为了理解为什么会出现错误,我们需要显示错误的代码。此代码有不同的错误(缺少分号,以及
main
的错误类型),并且在修复这些错误后可以干净地编译。没有办法知道可能出了什么问题