0

嗨,我有 1 个关于 C++ 虚函数的问题...

class base{
 public :
    base()  { a=5;}
    int a;
    virtual void print()=0;
    int get(){return a;}
    int get_var(){ a=5;  return a;}
};  

int main(void){
    base *p;
    cout <<"Get Call - No assign\n";
    cout <<"Value is :: "<<p->get()<<endl;
    cout <<"Get Call - assign value\n";
    cout <<"Value is :: "<<p->get_var()<<endl;
    return 0;
}

它的 o/p 是 :: Get Call - No assign Value 是 :: 5 Segmentation Fault

我不明白这种行为?
我能想到的一个原因是——因为基础是抽象类,即没有完整的实现,所以当我做 a=5 时它会崩溃。
但在第一次通话中,我也在使用一个,所以为什么它没有在那里崩溃
请帮助....

4

4 回答 4

3

根本原因:

您的指针p不指向任何有效对象,因此当您通过调用其上的成员函数来解除对它的引用时会 发生崩溃(实际上它是一个未定义的行为)。

当您声明一个指针仅指向任何随机地址时,您有责任使其指向一个有效对象,以便能够对指针执行任何有意义的操作。

解决方案:

你需要:

base *p = new base; 

或者

base obj;
base *p = &obj;

要使上述任何一个工作,base必须是非抽象类。在您的示例base中是一个抽象类(具有至少一个纯虚函数的类),对于这样的类,您不能创建它的任何对象(调用它的构造函数)。
因此,要解决这个问题,您需要创建一个派生自抽象类的派生类base,然后为派生类实现纯虚函数print(),从而使派生类成为具体类而不是抽象类。然后你可以查看工作中的动态调度(我猜那是你的目标

class Derived:public base
{
    public:
        virtual void print()
        {
            //Do some prints
        }
};

int main()
{
    Derived obj;
    Base *ptr = &obj;

    //or

    Base *ptr2 = new Derived;

    //.....Rest of your program as is
}
于 2012-08-28T12:35:47.767 回答
2

您没有初始化base *p;,因此在其上调用方法是未定义的行为(在您的情况下是段错误)。

另一方面,由于它base是一个抽象类,因此无法对其进行初始化。您必须提供在派生类printbase或派生类中的定义。

于 2012-08-28T12:36:25.787 回答
1

我能想到的一个原因是——因为基础是抽象类,即没有完整的实现,所以当我做 a=5 时它会崩溃。

不,崩溃是由取消引用未初始化的指针p(技术上未定义的行为)引起的。作为base抽象,没有办法创建它的实例:

base b;             // Illegal
base* p = new base; // Illegal 

并且发布的代码中没有派生的具体类。base您需要从纯虚函数派生和实现print()。类中的析构函数base也应该是virtual.

于 2012-08-28T12:38:18.413 回答
0

p是一个未初始化的指针。所以用它做几乎任何事情都是未定义的行为。

而“为什么不早点崩溃”的答案通常是“运气”(好坏,取决于你的看法)。具有未定义行为的程序可以做任何事情:似乎可以工作、崩溃、让你的鼠标爆炸等等。

于 2012-08-28T12:38:26.587 回答