有关一段带有模板、转换运算符和复制 ctor 的代码的问题

Questions about a piece of code with templates, conversion operator and copy ctor

本文关键字:运算符 转换 ctor 问题 代码 复制 一段      更新时间:2023-10-16

关于以下代码段的两个问题:

template <class T> class A {
protected:
    T j;
public:
    A(T k) :j(k) {cout << *this;}
    ~A() { cout << *this; }
    A(const A<T> &a) {
        j = a.j;
        cout << *this;
    }
    virtual void print() const {cout << j << ' ';}
    friend ostream &operator << (ostream &os, const A<T> &a) {
        a.print();
        return os;
    }
    operator T() {  return j;}
};
template <class T> class inherit:public A<T> {
    T field;
public:
    inherit(const T&t) :A<T>(t), field(1+t) {
        cout << *this;
    }
    void print() const {
        A<T>::print();
        cout << field << ' ';
    }
};
int main(){
    inherit <int> b(3);
    inherit <string> c("asdf");
    string k="str";
    c + k;//error no operator +
    b + 5;//no error
}
  1. 为什么inherit <int> b(3);会导致inherit的复制?为什么要复制而不是使用默认 ctor 从头开始创建inherit的新实例?

  2. 为什么b+5;会导致转换运算符operator T(),为什么c+k不会发生这种情况?

  1. 为什么inherit <int> b(3);会导致继承的复制?为什么要复制而不是使用默认 ctor 从头开始创建继承的新实例?

首先,它不会导致复制构造函数,并且实例实际上是从头开始创建的

未使用默认构造函数

,因为您没有调用默认构造函数。默认构造函数将使用空参数列表调用(除了,在这种情况下,您还必须省略括号以避免烦人的解析(:

inherit <int> b; // this would call the default constructor

如果将参数传递给构造函数,则将调用非默认构造函数。 inherit <int> b(3);会导致调用inherit(const T&)在此模板实例中inherit(const int&) 。它不是inherit的复制构造函数。

  1. 为什么 b+5; 会导致转换运算符运算符 T((

因为没有定义operator+(const inherit<int>&, int)也没有类似的成员函数。因此,重载解析会查找可将操作数隐式转换为的替代项。碰巧的是,存在内置operator+(int, int),并且inherit<int>可以隐式转换为A<int>(因为它是基数(,A<int>可以转换为int(因为它是转换运算符(。因此,该操作员最终被调用。

为什么 C+K 不会发生这种情况?

首先,您甚至无法实例化inherit <string>因为构造函数尝试向参数字符串添加 int,该字符串没有有效的重载。

现在,假设构造函数是固定的,以便inherit<string>可以存在,c + k似乎仍然不起作用。我怀疑这是因为字符串需要比int更多的转换,因为它不是基元,并且您已经达到了用户定义的转换序列可以具有的最大深度。您可以将inherit<string>显式转换为string以缩短转换顺序:

static_cast<std::string>(c) + k; // this works
  1. 为什么 b+5; 会导致转换运算符运算符 T((,为什么 c+k 不会发生这种情况?

编译器抱怨的是一段完全不同的代码。如果你去掉里面的+main(),你可以看到它仍然抱怨一个operator+

http://melpon.org/wandbox/permlink/H3cUUaf8fSnbYDwA

原因是这一行:

inherit(const T&t) :A<T>(t), field(1+t) {

你有1 + t,其中t std::stringstd::string 没有运算符 + 表示int,所以这不会编译。