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;
};