0

我有两个结构相似的课程。

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会起作用吗?将aobj被正确转换并解释B &为何时调用 B 的复制构造函数?

编辑:怎么样?

B bobj(aobj)
4

3 回答 3

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如果您想危险地生活,您可能可以通过将对象显式重新解释为 a 来摆脱困境B,因为它们都是具有相同数据成员的标准布局类型:

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

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

如果这一切听起来工作量太大,为什么不使用std::string它来为您处理内存管理?

于 2013-02-21T07:30:19.623 回答
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 类,它们是生成的。

然后要么需要修复生成器,要么您将不得不编写自己的适配器。

于 2013-02-21T07:41:19.367 回答
0

您可以通过考虑以下注意事项来做到这一点:

1) char* b产生问题。当您将 aobj 复制到 bobj 时,指针的值aobj.b将被复制到bobj.b这意味着它们都引用相同的内存位置并且像这样更改一个:aobj.b[0] = 'Z'将导致bobj.b更改。

您可以通过将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 显式定义构造函数和赋值运算符。这些是更推荐的。

于 2013-02-21T07:37:51.410 回答