我有一个从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") {
^
问题:
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 {
^~~~~~~~~~~~~~
答案 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)
- 定义这样的转换是不是一个坏主意?这会破坏任何推荐的编程实践吗?
醇>
是的,继承一个不是为它设计的课通常是一个坏主意。看起来你的问题(“添加一些函数”)的方法(“继承”)来自其他编程语言,其中继承是常见的做法,例如Java。
在C ++中,您拥有值语义和一系列强大的抽象机制,继承通常会产生比解决更多的问题,因为某些函数可能不是虚拟的,并且为了以多态方式存储对象,您必须使用动态分配
我该如何做到这一点?
你有没有理由不使用标准的C ++方式 - 全局函数?它们有很多优点:可以在不改变类的情况下添加它们,也不必强迫用户使用不同的类(派生的类),并通过限制成员函数(可以直接访问类内部)来增加封装。