.NET:继承修改基类(C+;+;转换)

.NET:继承修改基类(C+;+;转换),.net,c++,inheritance,.net,C++,Inheritance,我有两节课。基类是A。继承的类是B。我希望将基类从一个对象复制到另一个对象的基类中,而不影响原始类。但是,.NET似乎忽略了复制。这在.NET中是不可能的。我知道C++是可能的。我已经包含C++代码来说明我正在尝试实现什么。 我的理解是,在这个特定的示例中,我可以直接分配值bClass.ValueA=aClass.ValueA。但是如果A级有私人成员呢?这是不可能的 示例类 Public Class A Public ValueA As String End Class Public

我有两节课。基类是A。继承的类是B。我希望将基类从一个对象复制到另一个对象的基类中,而不影响原始类。但是,.NET似乎忽略了复制。这在.NET中是不可能的。我知道C++是可能的。我已经包含C++代码来说明我正在尝试实现什么。 我的理解是,在这个特定的示例中,我可以直接分配值bClass.ValueA=aClass.ValueA。但是如果A级有私人成员呢?这是不可能的

示例类

Public Class A
    Public ValueA As String

End Class

Public Class B
    Inherits A
    Public ValueB As String

End Class
代码

    Dim aClass As New A
    Dim bClass As New B

    aClass.ValueA = "AClass"

    bClass.ValueA = "BClass"
    bClass.ValueB = "BClass"

    Dim baseBClass As A
    baseBClass = CType(bClass, A)
    baseBClass = aClass
结果:

aClass.ValueA=“aClass”

bClass.ValueA=“bClass”

b class.ValueB=“b类”

baseBClass.ValueA=“AClass”

预期结果:

aClass.ValueA=“aClass”

b class.ValueA=“AClass”

b class.ValueB=“b类”

baseBClass.ValueA=“AClass”

C++解释比较

#include <string>
#include <iostream>

using namespace std;

class A {
public:
    string ValueA;
};

class B : public A {
public:
    string ValueB;
};



int main(int argc, char *argv[]) {
    A aClass;
    B bClass;
    aClass.ValueA = "AClass";

    bClass.ValueA = "BClass";
    bClass.ValueB = "Blcass";

    cout << aClass.ValueA <<endl;
    cout << bClass.ValueA << endl;
    cout << bClass.ValueB << endl;

    A *baseBClass;
    baseBClass = (A*) &bClass;
    *baseBClass = aClass;

    cout << aClass.ValueA <<endl;
    cout << bClass.ValueA << endl;
    cout << bClass.ValueB << endl;
    cout << baseBClass->ValueA << endl;


    return 0;
}
我得到这个错误:

表达式是一个值,因此 不能是分配的目标


为了方便起见,我刚刚对您的代码行进行了编号:

1 Dim aClass As New A
2 Dim bClass As New B

3 aClass.ValueA = "AClass"

4 bClass.ValueA = "BClass"
5 bClass.ValueB = "BClass"

6 Dim baseBClass As A
7 baseBClass = CType(bClass, A)
8 baseBClass = aClass

在第4行为您分配了bClass.ValueA值“bClass”,因此这就是您的输出的原貌。

当您分配baseBClass=aClass时,您分配的是一个指向aClass的指针

这将替换存储在此处的bClass指针:baseBClass=CType(bClass,A)

我认为您可能需要在中使用复制构造函数来实现所需的效果

Dim aClass As New A
Dim bClass As New B

aClass.ValueA = "AClass"

bClass.ValueA = "BClass"
bClass.ValueB = "BClass"
好的,现在在堆上分配了两个实例,以及引用它们的两个变量。大概是这样的:

Variable       Instances on the heap
--------       ---------------------

aClass ------> Instance of class A

bClass ------> Instance of class B
(顺便说一下,您的命名很混乱。aClass和bClass根本不是类;它们是引用实例的变量。)

然后你要这样做:

Dim baseBClass As A
baseBClass = CType(bClass, A)
baseBClass = aClass
现在有三个变量,但两个实例与之前相同。其中两个变量(bClass和baseBClass)都引用同一实例:

Variable          Instances on the heap
--------          ---------------------

aClass ---------> Instance of class A

baseBClass -\
             >--> Instance of class B
bClass -----/
baseBClass变量与bClass变量的类型不同,但它们都引用同一实例

现在您可以这样做:

Dim baseBClass As A
baseBClass = CType(bClass, A)
baseBClass = aClass
它将baseBClass变量中的引用替换为不同的引用,具体来说,是对上面标记为“类a实例”的对象的引用:

你只是在分配参考资料。实际上,您从未复制任何数据


但从我收集的您的描述来看,您希望其中一些赋值将引用从一个变量复制到另一个变量,而其他赋值将对象的内容从一个实例复制到另一个实例?这两件事都是用同一个赋值运算符表示的。您希望编译器如何知道哪个是哪个?

如果我理解正确,您要做的是从一个对象实例中剥离部分状态,然后将其推入另一个实例的咽喉。也就是说,您想要违反封装

有一些方法可以做到这一点,实际上是工作,而且不会违反封装,但老实说,我觉得这是一个非常糟糕的设计——一个C++愿意让你逃脱,但一个糟糕的设计。这听起来像是在试图滥用继承,而实际上应该使用聚合。你是说“一个B的实例就是一个A”,其实这并不合适。相反,它应该是“一个B的实例有一个A”。或者用代码表示:

Public Class A
    Public ValueA As String
End Class

Public Class B
    Public A As A
    Public ValueB As String
End Class

请注意,B不再从A下降;相反,它有一个对a实例的引用。当你创建一个B时,你需要某种方法给它一个a实例,这样你就可以初始化该字段——也许B的构造函数可以创建一个a并将引用分配给该字段,或者你可以将a的一个实例传递给B的构造函数。稍后,如果您确定它引用的是错误的A实例,您可以将其更改为引用其他实例。

一种替代方法是使用C#类执行指针操作并向B类添加扩展方法。这将非常类似于C++解决方案。这似乎是最好的解决方案,因为它几乎与C++实现完全相同。 相反,我使用了反射。这只是一个肤浅的副本,但在这种情况下,这并不重要。C++默认复制构造函数只是一个浅克隆。通过一些修饰,您可以检查IClonable是否存在,并尝试克隆它,否则将实例化一个新对象。我已将此更新为包含私人成员


基类克隆

    Dim aClass As New A
    Dim bClass As New B

    aClass.ValueA = "AClass"

    bClass.ValueA = "BClass"
    bClass.ValueB = "BClass"

    Dim baseBClass As A
    baseBClass = CType(bClass, A)
    baseBClass = aClass
这是我的解决方案所基于的站点。这是一个肤浅的克隆,但易于快速实现

此解决方案更好,因为它尝试在支持IClonable的对象上进行深度克隆,否则它只会设置一个新实例。

克隆例程:

这是一个有趣的网站,介绍了各种克隆技术。

另一个有趣的资源。

关于深度克隆的讨论

我不明白您为什么要
bClass.ValueA=“AClass”
。你确实设置了
bClass.ValueA=“bClass”
,但是他设置了baseBClass=aClass,我想他打算将值aClass.ValueA复制到bClass.ValueAThanks Jeroen,我已经解释了我的意思。我想因为在第8行,baseBClass现在应该是一个a类,当他做作业时,baseBClass应该具有复制的aClass值。直接赋值可以,但如果基类有私有成员该怎么办。@Shiftbit:您希望bClass在哪一行获得您希望它获得的值?为了实现这一点,您确实需要指针,现在您只处理引用。在C#中,可以使用不安全关键字来处理指针。在VB中,这是不可用的。复制构造函数或组合而不是继承会有帮助,但如果这些类来自封闭的库。Eek。。人力资源部好吧,我们就这样吧