C++ 访问父类C+中的子成员+;

C++ 访问父类C+中的子成员+;,c++,inheritance,C++,Inheritance,我面临的情况是,我需要访问父类中的子成员变量。我知道这是违反OO原则的,但我必须处理这样一个场景:数百个类从一个类继承,其中一半停止使用父变量之一,并声明和使用它们自己的(需要从int切换到int[]显然,这样做的人没有考虑在父类中应用这些更改) 一种选择是使用一个虚拟函数来处理它,但这意味着我必须更改数百个文件/对象中的代码,并测试其中的每一个。因此,我认为,如果可以使用一些老式的C指针魔法来访问父方法中的变量,这将消除数百个虚拟函数的需要。 基本上这就是我想要实现的目标: class Pa

我面临的情况是,我需要访问父类中的子成员变量。我知道这是违反OO原则的,但我必须处理这样一个场景:数百个类从一个类继承,其中一半停止使用父变量之一,并声明和使用它们自己的(需要从int切换到int[]显然,这样做的人没有考虑在父类中应用这些更改)

一种选择是使用一个虚拟函数来处理它,但这意味着我必须更改数百个文件/对象中的代码,并测试其中的每一个。因此,我认为,如果可以使用一些老式的C指针魔法来访问父方法中的变量,这将消除数百个虚拟函数的需要。

基本上这就是我想要实现的目标:

class Parent
{
    void DoSomething()
    {
        // This is what I need
        childMember = 0;
    }
}

class Child1 : Parent
{
    int childMember;
}

class Child2 : Parent
{
    int childMember;
}
请让我知道这是否可能。如果是,我如何做到这一点。
欢迎其他建议,但请记住,我只想在父类中进行更改。

TIA.

没有安全、可靠的方法来使用指针执行此操作。您可以使用巧妙的指针偏移进行操作,但这取决于所有子类中出现在同一位置的
childMember

唯一干净的方法是使用虚函数方法

如果
父类
类至少有一个虚拟函数(不一定是
DoSomething
),还有一种令人讨厌的方法:

void DoSomething() {
    if (Child1* child = dynamic_cast<Child1*>(this)) {
        child->childMember = 0;
    } else if (Child2* child = dynamic_cast<Child2*>(this)) {
        child->childMember = 0;
    } // and so on, and so forth
}
void DoSomething(){
if(Child1*child=dynamic_cast(this)){
child->childMember=0;
}else if(Child2*child=dynamic_cast(this)){
child->childMember=0;
}//等等,等等
}

(如果
Parent
没有虚拟函数,那么
dynamic\u cast
将不起作用。但是,任何设计从中继承的类都应该至少有一个虚拟函数,即使它只是析构函数。)

static\u cast(this)->childMember=0应该可以工作。

显然,您有一些派生类的子集,这些派生类使用了
childMember
。 对于这些类,可以调用一些方法“DoSomething()”。我想对于所有其他派生类,方法
DoSomething()
都不适用。为什么不为这组派生类创建另一个抽象级别呢

class Parent
{
    // no DoSomething()
}

class ChildMemberClasses : Parent
{
    int childMember;

    void DoSomething()
    {
        // code that uses childMember
    }
}

class ChildWithChildMember : ChildMemberClasses
{
    // other stuff
}
如果
DoSomething()
对没有childMember的类有一定的意义,您仍然可以在
父类中将它定义为虚拟方法。像这样:

class Parent
{
    virtual void DoSomething()
    {
        // code that does not use childMember
    }
}

class ChildMemberClasses : Parent
{
    int childMember;

    void DoSomething()
    {
        // code that uses childMember
    }
}

class ChildWithChildMember : ChildMemberClasses
{
    // other stuff
}
您可以使用来实现这一点

template<typename T>
class Parent
{
    void DoSomething()
    {
        // This is what I need
        T::childMember = 0;
    }

    virtual ~Parent() {}
};

class Child1 : Parent<Child1>
{
  int childMember;

  friend class Parent<Child1>;
};
模板
班级家长
{
无效剂量测定法()
{
//这就是我需要的
T::childMember=0;
}
虚拟~Parent(){}
};
第1类:家长
{
国际儿童会员;
朋友班家长;
};

CRTP可能有助于:

struct Parent
{
    virtual void DoSomething() = 0;
};

template <typename Derived>
struct ParentProxy : Parent
{
    virtual void DoSomething()
    {
        Derived* p = dynamic_cast<Derived*>(this);
        p->childMember = 27;
    }
};

struct Child1 : ParentProxy<Child1>
{
    int childMember;
};

struct Child2 : ParentProxy<Child2>
{
    int childMember;
};

int main()
{
    Child1 child1;
    Child2 child2;

    Parent* objects[] = { &child1, &child2 };
    const int objectCount = sizeof(objects) / sizeof(objects[0]);
    for (int index = 0; index < objectCount; ++index)
    {
        Parent* parent = objects[index];
        parent->DoSomething();
    }
}
结构父级 { 虚空DoSomething()=0; }; 模板 结构ParentProxy:父级 { 虚空剂量测定法() { 派生*p=动态_投射(本); p->childMember=27; } }; 结构Child1:ParentProxy { 国际儿童会员; }; 结构Child2:ParentProxy { 国际儿童会员; }; int main() { Child1 Child1; 儿童2儿童2; 父*对象[]={&child1,&child2}; const int objectCount=sizeof(objects)/sizeof(objects[0]); for(int index=0;index剂量测量(); } }

我更改了代码,使其可编译—可能不是您所要求的—但随后提供了一个更好的(=可编译)示例代码。

是否可以创建一个包含您需要访问的childMember的中间抽象类

如果是:

class Parent
{
    virtual void DoSomething() //Parent must be a polymorphing type to allow dyn_casting
    {
        if (AbstractChild* child = dynamic_cast<AbstractChild*>(this)) {
            child->childMember = 0;
        } else //Its not an AbstractChild
    }
}

class AbstractChild : Parent 
{ 

     int childMember; 
     virtual void DoSomething() = 0;
}

class Child1 : AbstractChild {
     virtual void DoSomething() { }
}
类父类
{
virtual void DoSomething()//父项必须是多态类型才能允许dyn_强制转换
{
if(AbstractChild*child=dynamic_cast(this)){
child->childMember=0;
}否则,它不是一个抽象的孩子
}
}
类抽象子对象:父对象
{ 
国际儿童会员;
虚空DoSomething()=0;
}
类Child1:AbstractChild{
虚拟void DoSomething(){}
}

我没有得到静态演员的反对票。以下工作:

#include <stdio.h>
class B;
class A {
    public:
        A();
        void print();
    private:
        B *child;
};

class B : public A {
    friend class A;
    public:
        B();
    private:
        int value;
};

A::A(){
    child = static_cast<B*>(this);
}

void A::print(){
    printf("value = %d\n", child->value);
}

B::B(){
    value = 10;
}

int main(){
    B b;
    b.A::print();
}
#包括
乙级;;
甲级{
公众:
A();
作废打印();
私人:
B*儿童;
};
B类:公共A{
A级朋友;
公众:
B();
私人:
int值;
};
A::A(){
child=静态_cast(此);
}
void A::print(){
printf(“值=%d\n”,子->值);
}
B::B(){
数值=10;
}
int main(){
B B;
b、 A::print();
}

只需确保将A函数的声明放在B类的定义之后。您可以区分子类,因为如果找到了正确的子类,静态强制转换将返回NOTNULL。我发现这种方法也很有用,因为子类(B)几乎没有更改。

如果允许您更改子类源代码,您可以这样做:

class Parent
{
public:
    void DoSomething()
    {
        getMember() = 0;
    }
    virtual int & getMember() = 0;
};

class Child1 : public Parent
{
    int childMember;
public:
    int & getMember()
    {
        return childMember;
    }
};

class Child2 : public Parent
{
    int childMember;
public:
    int & getMember()
    {
        return childMember;
    }
};
否则,如果您的对象具有虚拟表(至少一个虚拟方法),则可以将static_cast()与C++11 typeid结合使用,因为它的速度大约是dynamic_cast的三倍:

#include <typeinfo>

class Parent
{
public:
    virtual void DoSomething();
};

class Child1 : public Parent
{
public:
    int childMember;
};

class Child2 : public Parent
{
public:
    int childMember;
};

void Parent::DoSomething()
{
    if (typeid(Child1) == typeid(*this))
    {
        auto child = static_cast<Child1*>(this);
        child->childMember = 0;
    }
    else if (typeid(Child2) == typeid(*this))
    {
        auto child = static_cast<Child2*>(this);
        child->childMember = 0;
    }
};
#包括
班级家长
{
公众:
虚空剂量仪();
};
类别Child1:公共父级
{
公众:
国际儿童会员;
};
第2类:公共家长
{
公众:
国际儿童会员;
};
void Parent::DoSomething()
{
if(typeid(Child1)=typeid(*this))
{
自动子对象=静态_转换(此);
child->childMember=0;
}
else if(typeid(Child2)=typeid(*this))
{
自动子对象=静态_转换(此);
child->childMember=0;
}
};

如果
不是
子项
,则您将获得UB:-问题是有很多不同的