我的代码如下 -
#include <iostream>
#include <string>
class A{
int a;
public: virtual void sayHello(){ std::cout << "Hello\n"; }
};
class B : private A{
std::string name;
public:
B(std::string _n): name(_n){}
void sayName(){std::cout << name << "says hello\n";}
void sayHello(){sayName();}
};
int main() {
A *ptr = new B("c++");
ptr->sayHello();
return 0;
}
生成以下编译器输出 -
错误:
prog.cpp: In function 'int main()': prog.cpp:20:22: error: 'A' is an inaccessible base of 'B' A *ptr = new B("c++"); ^
如前所述 - here,here&amp; here,我知道如何解决这个问题。使用public
继承而不是private
或protected
。
但是,如果我真的想隐藏基类背后的某些界面,是不是还有其他方法可以做到这一点?或者根据c ++ lang规范不可能这样做。
答案 0 :(得分:4)
如果您希望多态指针转换在类外部工作,那么继承必须是公共的。没有办法解决这个问题。
您可以添加在类中执行多态指针转换的成员函数:
class B : private A{
// ...
public:
A* getA() {
return this;
}
};
允许您执行此操作,同时仍允许私有继承:
B* b_ptr = new B("c++");
A* ptr = b_ptr->getA();
// ptr = b_ptr; // only allowed in member functions
我没有遇到真正的世界设计,这个技巧会有用,但适合自己。
PS。请记住,您应该销毁您创建的对象。还要认识到delete ptr
具有未定义的行为,除非~A
是虚拟的。
答案 1 :(得分:2)
即使我发现隐藏基类并希望将B
投射到A
也很奇怪,您可以使用operator A*()
。
它遵循一个最小的工作示例:
#include <iostream>
#include <string>
class A{
int a;
public:
virtual void sayHello(){ std::cout << "Hello\n"; }
};
class B : private A{
std::string name;
public:
B(std::string _n): name(_n){}
operator A*() { return this; }
void sayName(){std::cout << name << "says hello\n";}
void sayHello(){sayName();}
};
现在您可以将其用作:
int main() {
A *ptr = *(new B("c++"));
ptr->sayHello();
return 0;
}
甚至更好:
int main() {
B b{"c++"};
A *ptr = b;
ptr->sayHello();
return 0;
}
将广告投放添加到A&
就像添加定义为operator A&()
的成员方法return *this;
一样简单。
答案 2 :(得分:2)
有一个难看的方式:C风格演员。 C样式转换可以转换为无法访问的基类。这是唯一一种C风格演员可以做C ++演员无法做到的事情。从cppreference开始,当C样式广告(T) foo
尝试执行static_cast<T>(foo)
时,它可以做的不仅仅是static_cast
:
[p] ointer或对派生类的引用另外允许转换为指针或引用到明确的基类(反之亦然),即使基类是不可访问的(即,这个强制转换会忽略私有继承说明符。
重点增加
因此,您可以这样做:
int main() {
A *ptr = (A *) new B("c++");
ptr->sayHello();
return 0;
}
这很丑陋,它带有铸造的所有缺点,特别是C风格的演员表。但它确实有效,而且是允许的。
答案 3 :(得分:0)
如果您想要隐藏A
是B
的基础,那么这是有效的。
但你分配了
A *ptr = new B("c++");
打破隐藏,因为您使用A*
。所以c ++会生成错误,因为依赖项是隐藏的。你可以做到
B *ptr = new B("c++");
虽然。