在基础分配中导出的存储然后调用基函数

时间:2017-01-01 21:47:39

标签: c++ oop abstract-class virtual-functions

我来自Java,对C ++来说有点新鲜。 在Java中,我有可能这样做:link to code

我创建了一个抽象基类Mother,在同一个基类的公共函数中使用了一个纯虚函数。

我试过了:

class Mother {
    private:
        virtual void bar() = 0;
    public:
        void foo();
};

void Mother::foo() {
    // ... some code
    bar();
}

class Child0: public Mother {
    private:
        void bar();
};

void Child0::bar() {
    std::cout << "Child0" << std::endl;
}

class Child1: public Mother {
    private:
        void bar();
};

void Child1::bar() {
    std::cout << "Child1" << std::endl;
}

// main code
int main() {
    Mother mother;
    if(condition) {
        Child0 child;
        mother = child;
    } else {
        Child1 child;
        mother = child;
    }
    mother.foo();
}

但是我收到编译错误:

main.cpp:35:12: fatal error: variable type 'Mother' is an abstract class
    Mother mother;
           ^
main.cpp:5:22: note: unimplemented pure virtual method 'bar' in 'Mother'
        virtual void bar() = 0;
                     ^

我错过了什么?

2 个答案:

答案 0 :(得分:3)

与Java不同,C ++具有值语义而没有隐式指针:当您声明Mother mother;时,您将获得Mother的实际实例。不多也不少。除了你的情况,Mother是抽象的:你不能有一个Mother的实例! 稍后执行mother = child;只会将孩子的Mother部分分配到mother。这称为“对象切片”,因为您希望复制的子部分也会被切掉。

要解决此问题,您需要使用指针或引用,它们都可以引用动态类型与其静态类型不同的对象(例如,实际为Mother的{​​{1}})。我将使用最简单的拥有指针std::unique_ptr

Child0

请注意,我也已切换到动态分配:您的两个子实例是自动变量,这意味着它们在范围int main() { std::unique_ptr<Mother> mother; if(condition) { mother = std::make_unique<Child0>(); } else { mother = std::make_unique<Child1>(); } // At this point, *mother is of static type Mother, // but of dynamic type Child0 or Child1. mother->foo(); } 的末尾死亡。 std::make_unique构造一个具有动态生命周期的对象:它只会在持有它的{}时死亡。

如另一个答案中所述,由于您的子对象将以多态方式被破坏,因此unique_ptr的类型,Mother的析构函数应该Mother正确分派。< / p>

virtual

答案 1 :(得分:2)

您缺少object slicing陷阱,并且还有未定义的行为:分配

    window.onbeforeunload = function(e){
      gapi.auth2.getAuthInstance().signOut();
    };

mother = child; 获得&#34;切片&#34;降至child,删除任何多态行为。

如果您希望保留多态性,请使用指针:

mother

确保Mother *mother; if(condition) { mother = new Child0; } else { mother = new Child1; } mother->foo(); delete mother; 有一个虚拟析构函数。

请注意,您不能再使用内部作用域中的对象,因为一旦作用域结束,指针就会变为无效:

Mother
相关问题