适用于派生类的C++中的'Using'关键字

7 c++ inheritance using-declaration

我最近发现了一个using关键字的新应用; 不是参考namespace功能,而是在派生类声明中.就我而言,这与围绕'operator ='成员函数的问题是相关的.

鉴于声明,我有一种情况:

class CString{
public:
    ...//Various functions.
    operator=(const CString &cString)
    {
        //code to share internal array and increment reference count
    }
    operator=(const wchar_t *pstrString)
    {
        //code to create a personal internal array,
        //resize it appropriately and copy the pstrString argument.
    }
    ...
};

class CStringEx : public CString{
    ...//various members that expand upon CString's abilities.
};
Run Code Online (Sandbox Code Playgroud)

......一个CStringEx没有按我的预期工作的对象:

CStringEx cString;

cString=L"String contents";
Run Code Online (Sandbox Code Playgroud)

而是生成了编译器错误,声明' CStringEx没有'operator =()'函数,该函数接受类型为wchar_t* ' 的参数(或 - 非常接近 - 对该效果的单词).经过相当多的研究后,我了解到这是因为即使operator=派生类的自动编译器生成的成员函数也会覆盖从其父类继承的那些成员函数.这似乎违反直觉,用户 - 联合国对我友好.

但是,如果我添加一个using关键字:

class CStringEx : public CString{
public:
    using CString::operator=;
    ...
};
Run Code Online (Sandbox Code Playgroud)

...子类现在使用其父operator=成员函数,一切都很好.

到现在为止还挺好.但是,经过对这里和其他地方的进一步阅读,我了解到许多程序员不喜欢using为此目的而使用.例如,我已经阅读了一些评论员,他们描述了可能不需要的副作用,例如从父母那里获取所有运算符=.但是,除了在非常具体的情况下,我不明白为什么继承所有父成员函数会是和问题.如果这是主要问题,有人可以解释这样做的一般危险吗?

我能想到的唯一选择是在子类中为它的父元素的每个 operator=成员函数写出存根函数,然后显式调用那些相应的成员函数:

class CStringEx : public CString{
public:
    ...
    const CStringEx& operator=(const wchar_t* pstrString)
    {
        CString::operator=(pstrString);
        return *this;
    }
    const CStringEx& operator=(const CString &cString)
    {
        CString::operator=(cString);
        return *this;
    }
    ...//and so on...
};
Run Code Online (Sandbox Code Playgroud)

与版本相比,using CString::operator=这看起来非常难看,麻烦和混乱.那么,为什么不使用using关键字呢?

Mar*_*k B 1

这有点主观,所以让我们回顾一下我们所知道的:

如果using这是适合该工作的工具,那么您应该使用它。那是说:

  • using始终引入所有父方法/运算符,甚至是您从未打算添加的新添加的方法/运算符。当有人创建与子对象不能很好交互的父赋值运算符时,这甚至可能导致代码损坏。
  • 引入父级的复制赋值运算符意味着您可以CStringEx从 a创建 aCString但也许这是预期的行为。
  • 未来的读者/维护者可能不熟悉使用语法的运算符,并且可能会使代码稍微难以理解。

鉴于您最初质疑它(基于您所听到的事情)以及上述几点,让我们退一步看看您的设计。有CStringEx两种可能性:

  1. 它有额外的数据成员。在这种情况下,我愿意断言继承父运算符在某些或所有情况下都会出错,因为子类成员不会在赋值中得到处理。
  2. 它没有额外的数据成员,它只提供额外的代码功能。在这种情况下,请不要尝试使用子类。相反,编写在(迭代器)范围或(如果必须的话)对象上运行的自由函数算法CString