简体   繁体   English

C ++在子类中更改父类

[英]C++ Changing the parent class within the child class

My very first post here! 我的第一篇文章在这里! I have been using this site for many years as a reference and to find solutions to common problems. 我多年来一直在使用此站点作为参考,并找到常见问题的解决方案。 Unfortunately this problem I am facing is one that have not been found here yet! 不幸的是,我面临的这个问题是这里还没有发现的问题! So here it is. 就是这样 I have been working on a project for some time now. 我从事一个项目已有一段时间了。 My program has several thousand lines of code so I will not post it all here. 我的程序有几千行代码,所以我不会在这里发布。 Basically, I have a subclass in which I wish to change the parent class to one that has been already initialized in my code some place. 基本上,我有一个子类,在其中我希望将父类更改为已经在我的代码中某个位置初始化过的子类。 I am not sure if this is possible or if it is good code practice. 我不确定这是否可行或良好的代码习惯。 But I will let you guys be the judge of that! 但是,我会让你们当裁判! Here is the problem I am facing: 这是我面临的问题:

#include <stdio.h>

class Base

    public:
        int data;
        Base(int);
};

class Child : public Base
{
    public:
    Child(void);
        void run(Base*);
};

Base::Base(int var)
{
    data=var;
}


void Child::run(Base* base)
{
      this = base //I know that you can create a reference to the parent class
                    //by casting this pointer to a Base pointer, but was wondering
                   //if you can do this the other way around. 
    printf("%d\n",Base::data);
}

int main()
{
Base* base1 = new Base(5);
Base* base2 = new Base(3);
    Child one();

one.run(base1);

    delete base1;
    delete base2;
    base1=0;
    base2=0;
    return 0;
}

So if this compiles(which it does not) it would outputt something like 5 and if I change the run method parameter to base2 it should print something like 3. Is this possible? 因此,如果编译(不编译),则会输出类似5的内容,如果我将run方法参数更改为base2,则应打印类似3的内容。这可能吗? Thank you! 谢谢!

You cannot do precisely what you want, but you may be able to do something similar. 您不能精确地做自己想做的事,但是您可以做类似的事情。 If the parent class has a copy constructor , which lets you create an instance which is a copy of another instance, then you can use that copy constructor to create your parent object while your child object is being constructed: 如果父类具有一个copy构造函数 ,它使您可以创建一个实例,该实例是另一个实例的副本,则可以在构造子对象时使用该副本构造函数创建父对象:

class Child : public Base
{
    public:
    Child(const Base &b) : Base(b) { ...}

Now you have a Child object whose Base parts are identical to those of another Base object. 现在,您有一个Child对象,其Base部分与另一个Base对象的Base部分相同。

No, you cannot do things like that. 不,你不能那样做。 This is a READ-ONLY pointer. This是一个只读指针。 The line 线

 this = base;

WILL generate a syntax error. 将会产生语法错误。

Base classes in C++ are static. C ++中的基类是静态的。 They cannot be changed at run time. 它们不能在运行时更改。

Although, if your classes (both the base and the child) do not have virtual functions, the follwoing WILL work: 虽然,如果您的类(基础类和子类)都没有虚函数,则下面的方法会起作用:

(Base&)*this = *base;

At the same time I would discourage you to do this. 同时,我不鼓励您这样做。 The reason of discouraging is because such code would be highly vulnerable for changes. 劝阻的原因是因为此类代码极易受到更改的影响。 For example, if virtual method will be added to either of the classes, then the VMT will be overwritten. 例如,如果将虚拟方法添加到任何一个类中,则VMT将被覆盖。 This may not work with multiple inheritance. 这可能不适用于多重继承。 In my experiments with MSVC I noticed that sometimes it changes the order of base classes in the binary layout of the class. 在我使用MSVC进行的实验中,我注意到有时它会更改基类在二进制布局中的顺序。

In other words, this can be used if you are absolutely sure of the layout that is used by compiler. 换句话说,如果您完全确定编译器使用的布局,则可以使用它。 If you are sure that compiler will not change this layout in the future. 如果您确定编译器将来不会更改此布局。 If not, better avoid this. 如果没有,最好避免这种情况。

The right approach is to create a special method and copy in the data field by field. 正确的方法是创建一种特殊的方法,然后逐字段在数据中复制。

Consider this to be const. 认为this是常量。 When you obtain a reference to the base class, you're simple obtaining a reference to some subset (portion) of the subclass; 当获得对基类的引用时,就很容易获得对子类的某些子集(部分)的引用。 the base class instance is tightly bound to the class-as-a-whole (subclass instance in this case). 基类实例与整个类紧密绑定(在本例中为子类实例)。 You can direct how that base class is initialized (see Ernest's response), but you cannot break that link. 您可以指示如何初始化该基类(请参阅Ernest的响应),但不能断开该链接。

Usually the memory layout of a class-with-base-class is something like: 通常,带有基类的类的内存布局类似于:

[ ... | [... | base-class | 基础类| ... ... .. ] .....]

It's literally embedded, as opposed to existing independently (the following is not normal, I'd even go so far as to state it never happens - but that's an internal compiler choice): 它实际上是嵌入式的,而不是独立存在的(以下情况不正常,我什至会声明它永远不会发生-但这是内部编译器的选择):

[ ... | [... | reference to-base-class | 参考基础类| ... ... .. ] [ independent base-class instance ] ... ... ..] [独立的基类实例]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM