继承类的意外转换

时间:2014-01-28 12:31:36

标签: c++ inheritance

我正试图制作一种“收藏品”。该类需要接受从基类继承的所有类。

例如:

想象一下,我们有一个名为“A”的基类,我们还有许多继承自这个类“A”的其他类。所以我们有,继承自“A”的类“B”,继承自“A”的类“C”,依此类推,我们有一个名为“collection”的类,它也继承自“A”。类“collection”有一个“std :: map”,使用“add”方法保存所有类,并可以使用“get”进行检索。

发生的事情是它以某种方式工作,但应用程序转换为“基类”而不是返回传递的类。

让我们转到代码(请参阅有关代码的注释以了解输出):

这是工作代码:

#include <iostream>
#include <string>
#include <map>

class A
{
public:
    virtual void saySomething()
    {
        std::cout << "Hello from A object" << std::endl;
    }
};

class B : public A
{
public:
    void saySomething()
    {
        std::cout << "Hello from B object" << std::endl;
    }
};

class C : public A
{
    void saySomething()
    {
        std::cout << "Hello from C object" << std::endl;
    }
};

class Collection : public A
{
public:
    void add(const std::string & key, A * value)
    {
        storage[key] = value;
    }
    A * get(const std::string & key)
    {
        return storage[key];
    }
private:
    std::map<std::string, A *> storage;
};

int main( int argc, char ** argv )
{

    B * b = new B;
    C * c = new C;
    Collection * col = new Collection;
    Collection * col2 = new Collection;
    col->add("b", b); // works, because "b" inherits from "A" class.
    col->add("c", c); // works, because "c" inherits from "A" class.
    col->add("col2", col2); // watch this part...
    col->get("b")->saySomething(); // works - Output: Hello from B object
    col->get("c")->saySomething(); // works - Output: Hello from C object
    return 0;

}

它有效,但当我尝试检索“col2”并使用他的方法时......

col->get("col2")->add("b", b);
// output: error: 'class A' has no member named 'add'

如果我没错,它需要工作,因为“get”方法返回对象,所以我有“col2”对象的方法对吗?如果你回答是,我们有同样的想法,我不知道发生了什么。在“b”和“c”对象上它返回对象并且我有“saySomething”方法,但是当我尝试检索“col2”时,它将对象作为“A”对象,因此错误:< / p>

  

'A类'没有名为'add'的成员

如果我这样做会变得更糟:

col->get("col2")->saySomething(); // output: Hello from A object

这个想法是,一个集合只接受从基类继承的类,并接受从同一基类继承的其他集合,如递归。

1 个答案:

答案 0 :(得分:2)

C ++具有静态类型,因此当您拥有类型为A的对象时 - 这就是您的get方法返回的内容 - 只能使用A中声明的方法。要在add的结果上调用get,您需要使用static_castdynamic_cast进行投射,或者完全重新考虑您的类层次结构。为什么Collection需要继承A? (并回答你的上一个问题,因为它继承了,如果你调用saySomething,它将调用A中声明的方法,因为Collection不提供自己的覆盖。)