在C ++中复制类似的类

时间:2013-02-21 07:13:13

标签: c++ reference casting constructor copy

我有两个类似结构的类。

class A{
    int a;
    char *b;
    float c;
    A(char *str) { //allocate mem and assign to b }
};

class B{
    int a;
    char *b;
    float c;
    B(char *str) { //allocate mem and assign to b }
    B(B & bref) { //properly copies all the data }
};

我想将B的对象复制到A的对象。以下转换是否正常?

A aobj("aobjstr");
B bobj("bobjstr");
bobj = aobj;    //case 1
bobj = B(aobj); //case 2

案例2会起作用吗?当调用B的复制构造函数时,aobj是否会被正确转换并解释为B &

编辑:怎么样?

B bobj(aobj)

3 个答案:

答案 0 :(得分:2)

不,如果不编写转换构造函数或转换运算符,则无法在不相关的类型之间进行隐式转换。据推测,你的编译器告诉你这个;我的错误如下:

error: no match for ‘operator=’ in ‘bobj = aobj’
note:  no known conversion for argument 1 from ‘A’ to ‘const B&’
error: no matching function for call to ‘B::B(A&)’

您可以通过向B提供转换构造函数来允许转换:

class B {
    // ...
    B(A const & a) { /* properly copy the data */ }
};

如果你不能改变类,那么你需要一个非成员函数来进行转换;但这可能只有在班级成员公开的情况下才有可能。在您的示例中,所有成员(包括构造函数)都是私有的,因此根本不能使用这些类。据推测,在您的真实代码中并非如此。

如果你想生活危险,你可能会明确地将A对象重新解释为B,因为它们都是具有相同数据成员的标准布局类型: / p>

// DANGER: this will break if the layout of either class changes
bobj = reinterpret_cast<B const &>(a);

请注意,由于您的类分配内存,因此可能需要在其析构函数中释放它;为避免双重删除,您还必须按照Rule of Three正确实现复制构造函数和复制赋值运算符。

如果这听起来太多了,为什么不使用std::string来处理内存管理呢?

答案 1 :(得分:2)

如果您尝试编译它,您会发现这些都不起作用。首先,你的构造函数是private

bobj = aobj;    //case 1

这会尝试使用签名调用赋值运算符:

B& B::operator =(A const&)

这不存在,编译将失败。

bobj = B(aobj); //case 2

这会尝试调用A::operator B(),它不存在,编译将失败。

最后:

B bobj(aobj)

这会尝试调用带有签名B::B(A const&)的构造函数,该签名不存在,编译将失败。

你说,

  

我无法更改/修改A类和B类,这些都是生成的。

然后需要修复生成器,或者你必须编写自己的适配器。

答案 2 :(得分:0)

您可以通过考虑以下注释来完成此操作:

1) char* b出现问题。当您将aobj复制到bobj时,指针aobj.b的值将被复制到bobj.b,这意味着它们都引用相同的内存位置并更改为:aobj.b[0] = 'Z'将导致bobj.b {1}}要改变。

您可以通过将b从指针更改为平面数组来解决此问题:

//...
char b[MAXLEN];
//...

更好的解决方案是定义一个构造函数(接受另一种类型)并重载赋值(=)运算符,至少对于类B,并处理指针赋值(为新指针分配缓冲区并将内容复制到它)。

2)更新:示例语法如下:

   bobj = B(reinterpret_cast<B&> (aobj));

   // or simply:
   bobj = reinterpret_cast<B&> (aobj);

3)请注意,这是危险的,不安全,不推荐。这意味着您的解决方案的设计可能会发生变化。例如,A和B都可以从公共基类继承; B继承自A;或者B明确定义了A类的构造函数和赋值运算符。这些更值得推荐。