考虑以下代码:
class Bas
{
public:
virtual void test() = 0;
};
class Sub : public Bas
{
public:
void test(){};
void subfunc(){};
};
int main()
{
Bas * bs = new Sub();
bs->test();
bs->subfunc(); //Gives error
return 0;
}
为什么不能在这里使用多态?我的意思是,对象bs是Bas和Sub类型,为什么只能使用Bas中的函数?
答案 0 :(得分:1)
您只能使用基类指针获取在基类中定义的那些函数。您的基类没有subfunc()
,这就是您收到错误的原因。以下代码可能适合您
class Bas
{
public:
virtual void test() = 0;
virtual void subfunc(){};
};
class Sub : public Bas
{
public:
void test(){};
void subfunc(){};
};
int main()
{
Bas * bs = new Sub();
bs->test();
bs->subfunc();
return 0;
}
答案 1 :(得分:0)
多态性对subfunc不起作用,因为它不是基类中的虚方法。
Polymorphism (subtyping in this case)仅适用于在基类中重写的虚方法。编译器使用该虚方法为每个类添加一个vtable,以便在运行时调用正确的方法(参见virtual method table)。
向Bas类添加一个没有实现的虚拟子函数。
class Bas
{
public:
virtual void test() = 0;
virtual void subfunc() = 0; //add this
};
答案 2 :(得分:0)
在else {
return Fib(n-1)+ Fib(n-2);
}
函数中,main
已知类型为bs
。
如果您希望编译器利用其类型Bas
(例如调用Sub
),您可以将subfunc
转发为bs
下的Sub
确保bs
确实具有Sub
类型的方法的条件。
class Bas
{
public:
virtual void test() = 0;
virtual bool isSub() const { return false; }
};
class Sub : public Bas
{
public:
void test(){};
virtual bool isSub() const { return true; }
void subfunc(){};
};
int main()
{
Bas * bs = new Sub();
bs->test();
if (bs->isSub()) {
assert(dynamic_cast<const Sub*>(bs));
static_cast<Sub*>(bs)->subfunc();
}
return 0;
}
答案 3 :(得分:0)
为什么不能在这里使用多态?
subfunc
不是virtual
,因此在对象的VMT中不存在,因此无法通过基类指针访问它。
我的意思是,对象bs是Bas和Sub类型,为什么只能使用Bas中的函数?
对象在内存中可能是Sub
,但bs
指针指向对象的Bas
部分。 C ++是一种类型安全的语言,subfunc
中不存在Bas
,因此编译器无法通过subfunc
指针到达Bas
。想想如果bs
指向完全不同的派生类对象而不是Sub
对象会发生什么:
class Bas
{
public:
virtual ~Bas() {}
virtual void test() = 0;
};
class Sub1 : public Bas
{
public:
void test() {};
void subfunc() {};
};
class Sub2 : public Bas
{
public:
void test() {};
void somethingElse() {};
};
void doTest(Bas *bs)
{
b->test(); // OK
b->subfunc(); // error!
// exists in s1, but not reachable.
// does not exist in s2 at all.
}
int main()
{
Sub1 s1;
doTest(&s1);
Sub2 s2;
doTest(&s2);
return 0;
}
如果编译器在被指向的对象中甚至可能不存在时,您期望它如何调用subfunc
?
多态性的全部意义在于隐藏实现并仅暴露可调用接口。 subfunc
不属于Bas
界面。
如果你真的想要调用subfunc
,你必须首先确保处理当前的对象类型,然后相应地调整指针以达到它。出于这个目的,C ++有dynamic_cast
:
void doTest(Bas *bs)
{
b->test();
Sub1 *s1 = dynamic_cast<Sub1*>(b);
if (s1) s1->subfunc();
Sub2 *s2 = dynamic_cast<Sub2*>(b);
if (s2) s1->somethingElse();
}