我在其他问题中读过它,但没有一个是类似的,有些是在构造函数中调用虚方法,有些是关于纯虚拟方法,但这里的问题是关于vituais方法不是纯粹的,而是虚拟的不需要在所有衍生类中实现的方法。如果实例化的类没有实现该方法,那么如果我们调用它,它会在逻辑上从基类调用该方法,并且它有时会崩溃。 我在想,为什么?什么是VTABLE(它进入的地方)?什么是解决它的最佳方法。
这是一个简单的例子,(避免回答像纯虚拟的那样)。
#include <iostream>
class Foo
{
public:
virtual std::string myString() {}
};
class Bar : public Foo
{
public:
};
int main(int argc, char ** argv)
{
Foo * bar = new Foo;
bar->myString();
return 0;
}
什么是最好的解决方案?
最好的答案将是解释为什么会发生这种情况的基础上的VTABLE,当然,选择一个解决方案并解释原因。这个想法不是基于意见。
答案 0 :(得分:2)
基类实现实现该函数,它只是错误地实现了它。它与vtable或任何复杂的东西无关。解决方案4首选(因为它可以防止构建错误的程序),如果不可能/期望1或2的顺序。
请注意,错误根本不与虚函数或一般的继承有关(您没有使用Bar
,您注意到了吗?)。它甚至与课程无关,但也会与任何独立的功能相关。考虑:
#include <iostream>
#include <string>
// Note: UB -- nothing returned
int getInt() {}
std::string getStr() {}
int main(int argc, char ** argv)
{
// This probably works (read access from an arbitrary
// location on the stack which is in the prog's address space)
std::cout << getInt() << std::endl;
// This will crash. operator<< will try to access memory through
// a pointer value which is some arbitrary byte pattern on the stack.
// Probably not in the prog's address space.
// Then the destructor for the temporary string will
// try to delete the same
// memory which will crash in any case, even if it happens to
// point to valid memory (which, alas, was never allocated).
std::cout << getStr();
std::cout << "Still alive?\n"; // never printed
std::cout.flush();
return 0;
}
为了防止原始代码发生错误,只需返回一个值即可。如果您实施该功能并且不抛弃或中止(这是三种选择),即如果您返回,则必须返回值:
#include <iostream>
class Foo
{
public:
virtual std::string myString() { return "test\n";}
};
class Bar : public Foo
{
public:
};
int main(int argc, char ** argv)
{
Foo * bar = new Foo();
std::cout << bar->myString();
return 0;
}
答案 1 :(得分:1)
VTABLE是一个指向虚方法的指针表。通常,指向VTABLE的指针在视图中是隐藏的,但它通常被实现为类实例中的第一个元素。
当派生类没有其父类实现为虚拟的成员函数时,将调用父类的方法。
答案 2 :(得分:0)
您的mystring
函数应该返回一个字符串。