#ifndef TEST_H
#define TEST_H
#include <iostream>
#include <string>
class A{
public:
virtual void test1() = 0;
virtual std::string test2() = 0;
};
class B : public A{
public:
void test1(){
std::cout << A::test2() << " World";
}
};
class C : public B{
public:
std::string test2(){
return "hello";
}
};
class C1 : public B{
public:
std::string test2(){
return "Sup";
}
};
#endif // TEST_H
我有一个只有纯虚方法的接口A.我有一个抽象类,希望实现test1
并使用test2
来实现test1
。
现在C和C1以及实现test2
但我不能在B级做std::cout << A::test2() << " World";
错误:无法调用成员函数'virtual std :: string A :: test2()' 没有对象
我如何在c ++中做这样的事情?
答案 0 :(得分:3)
不要挂在纯虚拟虚拟网络上。在A
中声明的两个函数都是虚函数,您可以这样处理它们。因此,B
test1
的实施应该只需拨打test2
。没有A::
限定符。这会进行虚拟调用,并最终会导致test2
的最衍生版本,即C
或C1
中定义的版本,具体取决于对象的类型。从A::
中删除A::test2()
后,以下代码正常工作(应该如此):
int main() {
C c;
c.test1();
C1 c1;
c1.test1();
return 0;
}
[work]$ g++ test.cpp
[work]$ ./a.out
hello WorldSup World[work]$
是的,您应该在输出中添加\n
。 <g>
答案 1 :(得分:2)
您的class B
需要继承class A
。
class B: public A ...
当然,调用A::test2()
将无效,因为该类未实现 - 它没有正文。您可以通过ALSO在A类中实现它来解决这个问题,如下所示:
std::string A::test2() { return "some string"; }
答案 2 :(得分:2)
如果您想要虚拟呼叫,请不要使用显式范围限定。使用A::test2
将尝试调用A::test2
,而无需动态调度。反过来,这将无法链接,因为A::test2
没有实现。
答案 3 :(得分:2)
错误消息暗示,在编译它时,B
未从A
继承,因此没有类型A
的对象来调用成员函数。您发布的代码给出了一个不同的错误:A::test2
未定义。
几乎可以肯定,你想虚拟地调用这个函数(即在C
或C1
或其他任何地方调用最终覆盖)。在这种情况下,根本不符合条件:
std::cout << test2() << std::endl;
您的代码尝试专门调用A
中声明的版本,而不是任何覆盖。如果这实际上是你想要的(我怀疑),那么需要定义该函数:
std::string A::test2() {
return "I'm a pure virtual function. Why are you calling me?";
}
请注意,由于语言中的怪癖,无法在类定义中定义纯虚函数;这个定义必须走出课堂。