访问一个我只想存在于派生类中的函数
Accessing a function that i want to exist only in a derived class
我有一个基类base和几个派生类:Derived1、Derived2和Derived3。
我希望在所有这些中都有Function funcOne,这样我就可以定期访问它,如下所示:
Base* d1 = new Derived1();
Base* d2 = new Derived2();
Base* d3 = new Derived3();
d1->funcOne();
d2->funcOne();
d3->funcOne();
但我希望在Derived1类中只有函数funcTwo。问题是,我想这样访问它:
d1->funcTwo();
除了用某种实现(例如)在基类中创建虚拟funcTwo之外,还有可能用其他方式来实现吗
void funcTwo(){ cout << "There is no funcTwo for this class" << endl; }
其他实现只针对Derived1类?
谢谢!
我能想到两个主要选项。
您可以在基类中实现一个虚拟funcTwo,如您的问题所述。这通常是不好的做法,因为funcTwo在Base、Derived2和Derived3的上下文中可能没有意义。如果API的误用没有编译,而不是抛出错误,或者更糟的是,无声地失败,这会更好。这看起来像:
class Base() {virtual void funcTwo() {throw runtime_error("This should not be called");};
Base *d1 = new Derived1;
Base *d2 = new Derived2;
d1->funcTwo(); //fine
d2->funcTwo(); //compiles even though it doesn't make semantic sense, throws an exception
或者,您可以在Derived1中实现funcTwo。然后,如果可能的话,可以尝试直接保持指向Derived1的指针,如果不可能的话可以使用dynamic_cast。这是最好的,因为对Base::funcTwo的直接调用将无法编译,并且可以使语义更接近实际要表达的内容。
Base *b = new Derived1;
Derived1 *d1 = new Derived1;
Base *d2 = new Derived2;
d1->funcTwo(); //fine
if ((d1 = dynamic_cast<Derived1*>(b)) d1->funcTwo(); //fine
if ((d1 = dynamic_cast<Derived1*>(d2)) d1->funcTwo(); //funcTwo is not called, no errors
b->funcTwo(); //fails to compile
除了在基类中创建一个虚拟funcTwo之外,是否可以用其他方式来完成它〔…〕
如果您想将所有指针统一处理为Base*
类型,则不需要。
也就是说,你可以这样做:
Derived1 *d1 = new Derived1(); // not treated as a base*
Base* b1 = d1;
Base* b2 = new Derived2();
Base* b3 = new Derived3();
d1->funcTwo(); // not treated as a base*
b1->funcOne();
b2->funcOne();
b3->funcOne();
你也可以动态抛出你的指针(但这是一个比我上面的代码更糟糕的解决方案):
void CallFunc2(Base* b) {
if(auto d = dynamic_cast<Derived1*>(b))
d->funcTwo();
}
客户代码:
Base* b1 = new Derived1();
Base* b2 = new Derived2();
Base* b3 = new Derived3();
CallFunc2(b1); // will call Derived1::funcTwo
CallFunc2(b2); // will do nothing
CallFunc2(b3); // will do nothing
是的,您有用于此目的的dynamic_cast
。如果您的Base
指针是Derived1
,则强制转换将起作用,然后您可以调用funcTwo()
。如果不是这样,演员阵容就会失败。
在大多数情况下,使用dynamic_cast
是一个设计缺陷。它对某些事情很有用,比如组件加载和版本控制,因为您不知道正在加载组件的哪个版本,所以您可以检查它是否支持更新的功能。
就你而言,这可能是错误的。
不管怎样,如果你必须这么做的话。
Base * b = getBasePtr(); // I don't know which one I got
Derived1 * d1 = dynamic_cast< Derived1 * >( b );
if( d1 )
d1->func2();
如果您根本不希望成员函数在Base
中,您可以使用static_cast
:向下转换指向具有该函数的正确类的指针
Base* b = new Derived;
static_cast<Derived*>(b)->func2(); // Call function only available in `Derived`
当然,这需要指针b
实际上是指向Derived
实例的指针,或者您有未定义的行为。
注意:有这样的下转换,并根据某个东西的类型做不同的事情,通常被认为是糟糕的设计。
我认为最好的办法是使用静态方法来尝试为您进行解析,并执行仅存在于派生类中的函数。
class Base {
public:
virtual ~Base() {}
virtual void func1() = 0;
};
class Derived1 : public Base {
public:
virtual ~Derived1() {}
virtual void func1() { std::cout << "Derived1::func1" << std::endl; }
void func2() { std::cout << "Derived1::func2" << std::endl; }
};
class Derived2 : public Base {
public:
virtual ~Derived2() {}
virtual void func1() { std::cout << "Derived2::func1" << std::endl; }
};
void func2(Base& b) {
Derived1* d = dynamic_cast<Derived1*>(&b);
if (d) d->func2();
}
void f() {
Base* b1 = new Derived1;
Base* b2 = new Derived2;
func2(*b1);
func2(*b2);
}
这种方法将花费dynamic_cast,但为您节省一个vtable查找,还将为您提供所需的行为。
- 多重继承中的派生类的行为类似于聚合
- 选择专用于派生实例的基类的类模板
- 从谷歌测试中的派生夹具派生夹具
- c++依赖于派生类的纯虚拟函数
- 类是否可以包含基类作为成员,该基类稍后专用于派生类
- C++是否可以创建依赖于单个构造函数参数的派生类而不是bass类
- 如何禁止派生类从基C++派生,但允许从另一个派生类派生
- 适用于具有常见属性但值不同的派生类的设计设置
- 如何测试从依赖于外部系统的外部基类派生的类
- 使基类指针的行为类似于C++中的派生类
- 自定义强制转换未应用于派生类的引用
- 如何设置仅对派生于不同类的类可见的方法
- 将派生类传递给专用于基类的模板函数
- 依赖于基类以获取派生类结果的C++函数
- 将专用基指针强制转换为专用于其他模板参数的派生指针("adding on"专用化)
- 访问一个我只想存在于派生类中的函数
- 将函数应用于包含的对象,前提是它们派生自基类型
- 派生自库中的std::exception:仅头文件解决方案是否适用于捕获异常
- 适用于调用派生类析构函数中的虚拟函数
- C++:访问仅存在于其中一个派生类中的变量