假设我有一个我无法改变的父类,它有一个将由孩子们使用的功能。这两个孩子很相似,但使用不同类型的数据。让我们说这个例子,一个包含一个带有相关方法的数组,另一个包含一个带有相关方法的二维数组。
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函数中我只能从父级访问数据和函数。
有没有办法做到这一点?也许使用模板?
答案 0 :(得分:1)
您的问题有几种解决方案。
动态广告
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 Parent {
virtual void doSomethingWithParent(Parent* parent) = 0;
};
class Child1 : public Parent {
void doSomethingWithParent(Parent* parent) {
//you now have Child1 API and parent object
}
};
int main() {
Parent parent;
Child1 child;
Child2 child2;
child1.doSomethingWithParent(parent);
child2.doSomethingWithParent(parent);
}
这样每个孩子都可能有不同的过载。
派生类应该实现细节,而不是基类来管理所有派生类。这简直是糟糕的设计。
答案 1 :(得分:0)
在为其中一个继承的类使用构造函数时,您正在创建指向基类的指针并创建新内存。当您调用属于基类的函数对其派生类之一执行某些操作时,派生类可以访问基类的受保护或公共成员变量和函数,编译器可能不知道哪个类型为明确地工作。如果您确切知道在基类中有多少种不同的派生类型,则可以拥有每种类型的公共枚举,并将其存储为私有成员。这是一个例子:
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 ) {}
};
通过这个例子,当你调用你的函数来完成工作时,它将根据TYPE做出决定,并且指向派生类型的指针被转换为基类型工作的指针,然后返回指针。
如果你确切知道你有多少派生类型,这将有效。如果派生类型的数量未知,那么我建议在基类中将doWork函数声明为纯虚拟,使基类成为一个抽象类,在这里你不能创建它的实例,任何派生类都必须实现纯虚拟函数,你可以让每个类覆盖它。
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;
};
dynamic_cast的概念仍然适用于doSomeWork()函数,但是由于实现是通过实现在类上完成的,因此不需要switch语句!这样做任何派生类都必须声明并实现此函数。现在,如果某个特定的派生类型没有用于此函数,您仍然必须定义它,但是您可以将正文的内容留空。