Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 继承类的意外转换_C++_Inheritance - Fatal编程技术网

C++ 继承类的意外转换

C++ 继承类的意外转换,c++,inheritance,C++,Inheritance,我想做一种“收藏”。此类需要接受从基类继承的所有类 例如: 想象一下,我们有一个名为“a”的基类,我们还有许多从这个类“a”继承的其他类。所以我们有,从“A”继承的类“B”,从“A”继承的类“C”,等等,我们还有一个从“A”继承的名为“collection”的类。类“collection”有一个“std::map”,其中使用“add”方法保存所有类,并可以使用“get”检索这些类 实际情况是,它以某种方式工作,但应用程序将转换为“基类”,而不是返回传递的类 让我们转到代码(请参阅代码上的注释以了

我想做一种“收藏”。此类需要接受从基类继承的所有类

例如:

想象一下,我们有一个名为“a”的基类,我们还有许多从这个类“a”继承的其他类。所以我们有,从“A”继承的类“B”,从“A”继承的类“C”,等等,我们还有一个从“A”继承的名为“collection”的类。类“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;

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

“class A”没有名为“add”的成员

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

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

其思想是,一个集合只接受从基类继承的类,也接受从同一基类继承的其他集合,如递归,因此,当您有一个类型为
A
的对象时,这就是
get
方法返回的结果-只能使用
A
中声明的方法。要对
get
的结果调用
add
,您需要使用
static\u cast
dynamic\u cast
进行强制转换,或者重新考虑您的类层次结构。为什么
Collection
需要从
A
继承?(为了回答您的最后一个问题,因为它继承了,如果您调用
saySomething
,它将调用
A
中声明的方法,因为
集合
不提供它自己的覆盖)。

您感到惊讶吗?您的
get
调用返回一个
A*
,并且
A*
是否有一个
add()
方法?此外,您的
集合
类继承自
A
,但不重写方法
saySomething()
,因此您为什么对输出感到惊讶?不要使用公共继承,除非继承的类是父类的“A”
Collection
不是
a
,因此从
a
公开继承它是一种糟糕的设计。如果你想访问不属于
a
接口的方法,你需要强制转换到
Collection
。@Nim-你说的没有意义,因为我知道a没有实现方法“get”但重要的是,从A继承的“集合”具有该方法。@Tilart-你能给我解释一下吗?“其思想是,一个集合只接受从基类继承的类,也接受从同一基类继承的其他集合,比如递归。”-这就是为什么该系列也从A继承的原因。-你有没有关于我如何在这种情况下实施“静态”或“动态”的例子我会看到更多关于这一点,谢谢。我为你看到以下选项:1。强制转换,例如动态强制转换(col->get(“col2”)->add(“b”,b);(您应该测试强制转换是否返回NOTNULL)2。将集合方法添加到基类3。使用访问者设计模式。我认为1是最糟糕的——石膏是危险的并发症,通常是设计错误的信号。您可以考虑将集合方法添加到<代码> A<代码>中,并在<代码> A/<代码>实现中抛出异常,而在<代码>集合中重写应该做什么。我喜欢您的答案。我在互联网上看到一些帖子,说演员阵容也是这样,很危险等等。关于在上添加集合方法我尝试了,但出现了错误。我认为您只添加了声明,而没有大括号中的函数体。我按照您所说的做了,首先我只做了声明,而没有函数体,以查看会发生什么,因为集合有方法,所以它可能会重写,但不起作用,所以我用大括号表示身体,它起作用了。但我认为这很奇怪。我是说类“A”就是“一切”,想象一下如果我有更多的类,我需要在A上声明所有的类?我要A类是一种类型,就是这样。有一种方法不需要声明类a上的所有方法就可以实现吗?非常感谢。
col->get("col2")->saySomething(); // output: Hello from A object