Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.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++_Oop - Fatal编程技术网

C++ 从父指针访问子数据

C++ 从父指针访问子数据,c++,oop,C++,Oop,假设我有一个不能更改的父类,它有一个将由子类使用的函数。这两个孩子很相似,但使用不同类型的数据。假设在本例中,一个包含具有关联方法的数组,另一个包含具有关联方法的二维数组 struct Parent { Parent* DoSomethingWithChildren(Parent &other) }; struct Child1 : Parent { int a[x]; }; struct Child2 : Parent { int b[x][y]; }; 现在

假设我有一个不能更改的父类,它有一个将由子类使用的函数。这两个孩子很相似,但使用不同类型的数据。假设在本例中,一个包含具有关联方法的数组,另一个包含具有关联方法的二维数组

struct Parent {
    Parent* DoSomethingWithChildren(Parent &other)
};

struct Child1 : Parent {
   int a[x];
};

struct Child2 : Parent {
   int b[x][y];
};
现在让我们假设我创建了两个孩子

Parent* child1 = new Child1();
Parent* child2 = new Child2();

child1.DoSomethingWithChildren(child2);
如果我没有弄错的话,DoSomethingWithChildren函数应该能够使用“this”指针访问child1,并且由于child2被传递给函数,因此也应该可以访问它

问题是在DoSomeThingWithChildren函数中,我只能从父函数访问数据和函数


有没有办法做到这一点?也许使用模板?

有几种解决方案可以解决您的问题

动态播放

class Parent {
    public:
        Parent* DoSomethingWithChildren(Parent& other) {
            Child* childPointer = dynamic_cast<Child>(&other);
            if(childPointer) {
                // now you have Child class API
            } else {
                // this was clearly not a Child object
            }
        }
};
这样每个孩子都可能有不同的过载


派生类应该实现细节,而不是基类来管理所有派生类。这只是一个糟糕的设计。

您正在创建一个指向基类的指针,并在为其继承的类之一使用构造函数时创建新内存。当调用属于基类的函数对其派生类之一执行某些操作时,如果该派生类可以访问基类的受保护或公共成员变量和函数,编译器可能不知道显式处理哪种类型。如果您确切地知道将有多少不同的派生类型,那么在基类中,您可以拥有每个类型的公共枚举,并将其存储为私有成员。以下是一个例子:

class Node {
public:
    enum TYPE {
      TYPE_ONE,
      TYPE_TWO,
    };

private:
    TYPE m_type;

public:
    explicit Node( Node::TYPE type ) : m_type( type ) {}

    Node* doSomeWork( Node* other );
}; // Node

Node* Node::doSomeWork( Node* other ) {        
    Node* pNode = dynamic_cast<Node*>( other );

    switch ( m_type ) {
        case TYPE_ONE: {

            // Do Work Here
            return pNode;
        }
        case TYPE_TWO: {

            // Do Work Here
            return pNode;
        }
        default: {
            // If derived type not defined either throw exception
            // or return a nullptr
            return pNode = nullptr;
        }
    }
}

class Type1 : public Node {
    // Member Variables Here

public:
    Type1() : Node( TYPE_ONE ) {}
};

class Type1 : public Node {
    // Member Variables Here

public:
    Type2() : Node( TYPE_TWO ) {}
};

dynamic_cast的概念仍然适用于doSomeWork()函数,但是由于实现是在一个类上逐个实现的,因此不需要switch语句!这样做,任何派生类都必须声明并实现此函数。现在,如果一个特定的派生类型对这个函数没有用处,您仍然必须定义它,但是您会将正文的内容保留为空。

首先,您的命名约定很糟糕。将它们命名为
Node
和ChildNode`或类似于
RootNode
Node
,因为
Parent*child=new child()看起来只是。。。不好。您可能希望在每个子类中覆盖
DoSomethingWithChildren
;虽然我怀疑提供的示例太抽象了。你打算对孩子们做什么应该会影响该功能的设计。这个函数是递归的吗?对不起,我使用泛型名称来回答这个问题。在我的实际代码中,它们有更多的描述性名称。对cmbasnett:我自己在父系统中实现该功能。我只是不能改变签名。任何事情都可以强迫,但要按照流程进行:重新设计。当你没有创造性的方法时,很难帮助别人。常见的习惯用法:
if(Child*childPointer=dynamic_cast(&other)){…}
Yes,但可能对新手不太友好,所以我发布了扩展版本。但很高兴提到这一点。:)假设我误解了作业,我实际上可以将家长的方法更改为虚拟方法。如何在父函数中访问其他子函数的数据?我应该能够将child1或child2传递给DoSomeThingWithParent函数。子版本数是否恒定?您是否有恒定数量的儿童可能持有的数据?哪个更小?在设计这种建筑时有很多因素。若第一个答案是正确的,那个么您可以简单地尝试对其他类型进行动态强制转换。也许有更好的方法,但不知道任务,我无法预见什么会更好。最好的办法是发布你的作业内容。
class Node {
public:
    enum TYPE {
      TYPE_ONE,
      TYPE_TWO,
    };

private:
    TYPE m_type;

public:
    explicit Node( Node::TYPE type ) : m_type( type ) {}

    Node* doSomeWork( Node* other );
}; // Node

Node* Node::doSomeWork( Node* other ) {        
    Node* pNode = dynamic_cast<Node*>( other );

    switch ( m_type ) {
        case TYPE_ONE: {

            // Do Work Here
            return pNode;
        }
        case TYPE_TWO: {

            // Do Work Here
            return pNode;
        }
        default: {
            // If derived type not defined either throw exception
            // or return a nullptr
            return pNode = nullptr;
        }
    }
}

class Type1 : public Node {
    // Member Variables Here

public:
    Type1() : Node( TYPE_ONE ) {}
};

class Type1 : public Node {
    // Member Variables Here

public:
    Type2() : Node( TYPE_TWO ) {}
};
class Node {
public:
    virtual ~Node(){}
    virtual Node* doSomeWork( Node* other ) = 0;  

protected:
    Node(){}
};

class Type1 : public Node {
public:
    // Must Be Implemented But Can Be Override
    Node* doSomeWork( Node* other ) override;       
};

class Type2 : public Node {
public:
    // Must Be Implemented But Can Be Override
    Node* doSomeWork( Node* other ) override;
};