从父指针

时间:2015-05-09 20:28:11

标签: c++ oop

假设我有一个我无法改变的父类,它有一个将由孩子们使用的功能。这两个孩子很相似,但使用不同类型的数据。让我们说这个例子,一个包含一个带有相关方法的数组,另一个包含一个带有相关方法的二维数组。

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函数中我只能从父级访问数据和函数。

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

2 个答案:

答案 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语句!这样做任何派生类都必须声明并实现此函数。现在,如果某个特定的派生类型没有用于此函数,您仍然必须定义它,但是您可以将正文的内容留空。