如何从继承类调用函数?

时间:2011-02-10 12:40:12

标签: c++ class

我有代码:

class A{ //base class
public:
    virtual std::string getString(){return "class A";}
};

class B: public A{
public:
    std::string getString() {return "it is B class";}
};

class C{
public:
    C(){
        B b;
        a = b;
    }
    std::string test() {return a.getString();}
private:
    A a;
};


int main()
{
    C c;
    std::cout << c.test();

    return 0;
}

c.test()说“A类”,但我如何从B类调用方法getString()而不是A?

谢谢!

4 个答案:

答案 0 :(得分:7)

问题是,您的B对象在分配给A对象时会被切片。这是因为您按值分配,而不是通过引用或指针分配。既然你像这样声明了a

A a;

在作业a = b期间发生的事情是b的实际状态被复制到a。但是,由于a是值对象,因此只复制对象A的{​​{1}}部分,并且其“B-ness”完全丢失!

为了避免这种情况,你需要将b声明为指针类型,如其他人所建议的那样(引用也可以,但是你需要大大改写你的例子,因为你不能分配给引用,只初始化它们)。如果a是指针(a),则作业A*会使a = b指向由a表示的对象,该对象仍为b因此,您将观察到您期望的多态行为。但是,在这种情况下,您必须确保B在退出构造函数后仍保持活动状态 - 否则您将留下悬空引用,这会导致未定义的行为(阅读:在被解除引用时,你不想发生的坏事。

由于@Nawaz已经显示了指针示例,我将使用引用给出另一个:

b

答案 1 :(得分:5)

你需要这样实现:

class C{
public:
    C(){
        a = new B;
    }
    std::string test() {return a->getString();}
private:
    A *a;
};

这将从B类调用getString()而不是A。

您尝试做的事情称为“动态多态”,它是通过类型基类的指针(或 reference )实现的({{1} }),但指针指向派生类类型的对象(A)。

答案 2 :(得分:1)

由于您的成员a不是A*,因此它是A个实例。因此,您只需将A部分B分配给变量a。如果您将a转换为A*,您将获得预期的结果。

答案 3 :(得分:1)

切片因此无效。 aA,不是B

要处理类成员变量,必须是指针或引用。

作为指针

class C{
public:
    C(){
        a = new B;
    }
    std::string test() {return a->getString();}
private:
    A *a;
};

作为参考

class C{
    public:
        C() : a( *(new B) )
        {
        }
        std::string test() {return a.getString();}
    private:
        A &a;
    };

当然我的代码产生了泄漏,但是可以使用虚函数。