私有继承和隐式转换

时间:2016-03-04 21:01:59

标签: c++ inheritance casting

我有一个从std::string私下继承的类,并添加了一些函数。我希望能够像std::string一样使用这个类,所以我试图定义一个隐式转换运算符(operator string())。但是,我一直收到inaccessible base错误。

#include <iostream>
#include <string>

using namespace std;
class Test:private string {
    int _a;
    public:
    operator string() {
        return "hello";
    }
};

int main() {
    Test t;
    if(t == "hello") {
        cout<<"world\n";
    }
}

错误:

trial.cpp: In function ‘int main()’:
trial.cpp:15:13: error: ‘std::basic_string<char>’ is an inaccessible base of ‘Test’
 if(t == "hello") {
         ^

问题:

  1. 定义这样的转换是不是一个坏主意?这会破坏任何推荐的编程实践吗?
  2. 我怎样才能做到这一点?
  3. 编辑:Clang更有帮助

    trial.cpp:8:5: warning: conversion function converting 'Test' to its base class 'std::basic_string<char>' will never be used
        operator string() {
        ^
    trial.cpp:15:8: error: cannot cast 'Test' to its private base class 'basic_string<char, std::char_traits<char>, std::allocator<char> >'
        if(t == "hello") {
           ^
    trial.cpp:5:12: note: declared private here
    class Test:private string {
           ^~~~~~~~~~~~~~
    

3 个答案:

答案 0 :(得分:4)

私有基类的转换功能违背了私有继承的目的。这就是为什么标准禁止这种行为的部分原因:

  

转换函数永远不会用于转换(可能是cv限定的)对象   到(可能是cv限定的)相同的对象类型(或对它的引用),到该类型的(可能是cv限定的)基类(或对它的引用),或者(对可能是cv-qualified)void

如果要访问基类,则应将继承设为公共。这使代码可以保持可读性和全面性,以便其他可能需要维护的代码。

答案 1 :(得分:2)

我知道有两种方法可以吸吮,但仍然有效。尽管如此......它并不是真的隐含着......

明确调用运算符的方法不那么糟糕:

</applet>

更可怕的方式是c式演员。

if(t.operator string() == "hello")

请注意,这会对基类指针执行if (*(string*)&t == "hello") ,而不是static_cast的邪恶兄弟。

来自显式演员的cppreference

  另外,允许将

指向或派生类的引用转换为指针或引用明确的基类(反之亦然),即使基类不可访问

答案 2 :(得分:1)

  
      
  1. 定义这样的转换是不是一个坏主意?这会破坏任何推荐的编程实践吗?
  2.   

是的,继承一个不是为它设计的课通常是一个坏主意。看起来你的问题(“添加一些函数”)的方法(“继承”)来自其他编程语言,其中继承是常见的做法,例如Java。

在C ++中,您拥有值语义和一系列强大的抽象机制,继承通常会产生比解决更多的问题,因为某些函数可能不是虚拟的,并且为了以多态方式存储对象,您必须使用动态分配

  

我该如何做到这一点?

你有没有理由不使用标准的C ++方式 - 全局函数?它们有很多优点:可以在不改变类的情况下添加它们,也不必强迫用户使用不同的类(派生的类),并通过限制成员函数(可以直接访问类内部)来增加封装。