【问题标题】:difference between assignment operator and type conversion funtion for converting user defined to another user defined赋值运算符和类型转换函数之间的区别,用于将用户定义转换为另一个用户定义
【发布时间】:2014-12-12 12:26:44
【问题描述】:
#include <iostream>
using namespace std;

// Assignment operator: allow implicit conversion from a particular type on assignments.
// Type-cast operator: allow implicit conversion to a particular type.

class car;

class bus
{

public:bus & operator = (car & b)
                                // implicit conversion by assignment operator
  {
    cout << endl << "Assignment operator of BUS " << endl;
    return *this;
  }

/*  operator  car () const      //    Type-cast operator
  {
    return (car ());            // error: invalid use of incomplete type ‘class car’
  }*/
};
class car
{
public:
  car ()
  {
  }
  car (const bus & b1)
  {
    cout << endl << "conversion constructor";
  }
  car & operator = (bus & b)    // implicit conversion by assignment operator
  {
    cout << endl << "Assignment operator of car " << endl;
    return *this;
  }
operator   bus () const       //    Type-cast operator
  {
    cout << endl << "Typecast operator-in car" << endl;
    return (bus ());
  }
};

int
main ()
{
  bus b;
  car c1 = b;                   // call convertion constructor of car object

  c1 = b;                       // call assignment operator of car
  // or 
  b = c1;                       // call assignment operator of bus

  car c2; 
  bus b2 = bus (c2);            //call   Type-cast operator of car`enter code here`

  // we cannot define  Type-cast operator in bus 
  // eventhough forward decleration is done 
  // error: invalid use of incomplete type ‘class car’
  // so car c=car(b)  is not possible

我的问题是从用户定义类型到另一种类型的隐式转换 1) 如果在两者中声明的赋值运算符都可以用于 bus = car 和 car = bus 那么为什么要使用复杂的 Type-cast 操作符语法呢?有什么区别吗 如果是这样的话 ? 2)上面提到的复制构造函数和转换构造函数之间是否有任何关系,我注意到的一个相似之处是在分配时调用和传递参数的复制构造函数和转换构造函数是不同的。是否有其他差异或相似之处。 3)虽然前向减速完成了,但是代码被注释了一个错误:“invalid use of incomplete type ‘class car’”,为什么?

提前致谢

【问题讨论】:

  • 你有一个不可能的循环:你的bus 类需要一个完全定义的car 类,而car 类需要一个完全定义的bus 类。你需要找到一种方法来打破这个循环,也许是通过一个通用的基类(感觉很自然,buscar 都会继承类似vehicle 之类的东西),也许这个基类可以是使用Curiously recurring template pattern
  • @JoachimPileborg 我不明白为什么你不能只为这个使用类外成员函数定义。
  • @T.C.当然,我只是不确定类型转换运算符的实际声明是否也需要完整的定义。

标签: inheritance c++11 constructor


【解决方案1】:

正如comments 中提到的 Joachim Pileborg,您可以使用 CRTP 来完成您所需要的:

// code could stand for more tidying, but you get the idea
#include <iostream>
#include <typeinfo>
using namespace std;

// Assignment operator: allow implicit conversion from a particular type on assignments.
// Type-cast operator: allow implicit conversion to a particular type.

template <typename T>
class Car
{
public:
  Car () = default;
  Car (const T & b1)
  {
    cout << endl << "conversion constructor to " << typeid(T).name();
  }
  Car & operator = (T & b)    // implicit conversion by assignment operator
  {
    cout << endl << "Assignment operator of car to " << typeid(T).name() << endl;
    return *this;
  }

  T type() const
  {
    cout << endl << "Typecast operator-in car to " << typeid(T).name() << endl;

    return T();
  }
};

class Bus : public Car<Bus>
{

public:
   Bus() = default;
   Bus(Car<Bus>& b)
   {
      *this = b;
   }

   Bus & operator = (Car<Bus> & b)  // implicit conversion by assignment operator
   {
      cout << endl << "Assignment operator of BUS " << endl;
      return *this;
   }

   Car  car () const      //  Type-cast operator
   {
      return Car<Bus>::type();
   }
};


int main ()
{
   Bus b;
   Car<Bus> c1 = b;                   // call convertion constructor of car object

   c1 = b;                       // call assignment operator of car
   // or 
   b = c1;                       // call assignment operator of bus

   Car<Bus> c2; 
   Bus b2 = Bus (c2);            //call   Type-cast operator of car
   return 0;
}

CRTP 或奇怪重复出现的模板模式允许我们使用模板,以便基类可以了解派生类。

在本例中,我们将 Car 设为模板类,而 Bus 派生自 Car&lt;Bus&gt;,允许我们将 Car 类中的转换为 Bus

Live Example


回答您的问题:

  1. 如果在两者中声明的赋值运算符都可以用于 bus = car 和 car = bus 那么为什么要使用复杂的类型转换运算符语法?

这里的问题是Car需要知道Bus的完整实现,而Bus需要知道Car的完整实现。看到这里的循环参考了吗?模板化,或者前向声明和使用指针可以让我们解决这个问题。

  1. 提到的复制构造函数和转换构造函数之间是否有任何关系

我不确定你在这里问的到底是什么,但我会试一试。接受另一种类型的构造函数可以被视为执行转换的“复制构造函数”,但这可能就是您所说的“转换构造函数”。

  1. 即使进行了前向声明,也会出现错误:“无效使用不完整类型‘class car’”为什么?

这让我们回到 #1 和循环引用。如果你前向声明,你可以使用指针来绕过它。

【讨论】:

  • "这里的问题是 Car 需要了解 Bus 的完整实现,而 Bus 需要了解 Car 的完整实现。"不,他们没有。两个类定义都不需要另一个类的完整定义;一些成员函数体可以,但这很容易通过在类定义之外定义它们来解决。
  • @T.C.您对这个特定用例是正确的。我认为 OP 做的事情比这里给出的要复杂一些。也许这有点矫枉过正。
  • 感谢专家解答
猜你喜欢
  • 2013-11-27
  • 1970-01-01
  • 2013-05-23
  • 1970-01-01
  • 2017-09-18
  • 2011-04-02
  • 2020-12-16
  • 2012-06-10
  • 1970-01-01
相关资源
最近更新 更多