C++ 私有继承与隐式转换

C++ 私有继承与隐式转换,c++,inheritance,casting,C++,Inheritance,Casting,我有一个从std::string私有继承的类,并添加了一些函数。我希望能够像使用std::string一样使用这个类,因此我试图定义一个隐式转换运算符(operator string())。然而,我不断得到不可访问的基错误 #include <iostream> #include <string> using namespace std; class Test:private string { int _a; public: operator s

我有一个从
std::string
私有继承的类,并添加了一些函数。我希望能够像使用
std::string
一样使用这个类,因此我试图定义一个隐式转换运算符(
operator string()
)。然而,我不断得到
不可访问的基
错误

#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";
    }
}
#包括
#包括
使用名称空间std;
类测试:私有字符串{
国际组织;
公众:
运算符字符串(){
回复“你好”;
}
};
int main(){
试验t;
如果(t==“你好”){
库特
  • 定义这样的转换是一个坏主意吗?这会破坏任何推荐的编程实践吗
  • 是的,继承一个不是为它设计的类通常是一个坏主意。似乎解决问题的方法(“继承”(“add some functions”)源自其他编程语言,继承是常见的做法,例如Java

    C++中的值语义和一整套强大的抽象机制,继承通常会产生比它解决的更多的问题,因为某些函数可能不是虚拟的,为了存储对象的多态性,必须使用动态分配。 我怎样才能做到这一点


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

    我知道有两种方法很糟糕,但仍然有效。不过,这并不是真正隐含的

    不那么可怕的方法是显式调用操作符:

    if(t.operator string() == "hello")
    
    更可怕的方式是c型演员

    if (*(string*)&t == "hello")
    
    请注意,这将对基类指针执行
    静态转换
    ,而不是它的邪恶兄弟
    重新解释转换

    在显式强制转换中:

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


    将函数转换为私有基类违背了私有继承的目的。这就是标准禁止此类行为的部分原因:

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


    如果你想访问基类,你应该公开继承。这可以使代码对其他可能需要维护它的人来说可读性和全面性。

    请以后发布完整的错误消息。“你好”不是std::string。我想我可以让它工作的一种方法是使用公共继承,并使派生类
    final
    。我没有在派生类中分配任何额外的内存,因此不应该调用析构函数(?)这是一个问题。这是私有继承。所以我不知道你为什么说继承是一个坏主意。我提到的要点一般适用于继承。你可以在你的初始帖子中添加你真正想要实现的功能吗,例如,你想添加到
    std::string
    的功能中,而这些功能是不能添加的吗在我需要的时候,我可以使用简单的函数来完成。但我不认为这是重点。我可能误解了你的问题,但因为其中一部分是关于编程实践的,我认为指出替代设计是合适的。一般来说,你应该选择完成工作但耦合最轻的关系,这将适用于在本例中,y用于释放函数。通过从字符串继承,您已经告诉编译器“Test”是一个字符串。通过私有化,您已经说了“但不要告诉任何人”。通过明确地编码cast运算符,您再次希望它是一个“字符串”……C++要求你有一点更果断……如果String的方法中任何一种不适用于你的类,这强烈地暗示了测试实际上不是一个字符串,但是可能有一个作为成员变量。一种使它隐式的方法是使用公共继承,对吗?我不重写任何<代码> STD::String < /Calp>函数,i没有分配任何额外的内存,我可以使我的类成为final,从而阻止其他人继承。这是否留下了公共继承仍然不好的原因?@user2308211我不知道,但这并不意味着我不知道有什么原因。我有一点不接受答案,just以防有人想出什么主意。但是谢谢你的帮助answer@user2308211我写这篇文章就是为了把信息放在这里。这是一个非常有趣的问题,我希望有人能想出一个很好的解决方案。stl类不应该从一个不成文的规则中派生出来,对吗?这是一个例外吗坏了?正如我在其他评论中提到的,不要重写任何
    std::string
    函数,我没有分配任何额外内存,我可以使我的类
    final
    @user2308211它们不是不应该派生的,而是大多数类(包括
    std::string
    )从缺少虚拟函数(最重要的是缺少虚拟析构函数)可以看出这一点因此,如果您要删除<代码> STD::String *<代码>到<代码>测试< /代码>实例,您将有未定义的行为,无论“代码>测试< /代码>是<代码>最终< /代码>。您应该考虑这一点,并且其他人不知道使用“代码>测试< /代码>的可能性。这是我再次投票的唯一主要原因。
    if(t.operator string() == "hello")
    
    if (*(string*)&t == "hello")