引用子变量的父类
Parent class referencing child variable
我有几个类似的类继承自同一个基类/接口(基类1),它们共享几个相似的函数,但也有自己独特的函数。它们也有自己不同类的成员变量,并且每个成员变量都继承自同一个基类/接口(基类 2)。是否可以在基类 1 中定义一个类型为 Base 类 2 的变量,然后在使用基类 1 的实际实现中,将 Base 类 2 类型的变量作为其正确类型。有点难以解释,所以下面简化了示例。
//Base-Class 1
class Shape
{
public Shape() {}
ShapeExtra m_var;
//The common functions
public GetVar(){ return m_var; }
}
class Circle : Shape
{
public Circle() { m_var = new CircleExtra(); }
public void CircleFunc()
{
m_var.CircleExtraFunc();
}
}
class Triangle : Shape
{
public Triangle() { m_var = new TriangleExtra(); }
public void TriangleFunc()
{
m_var.TriangleExtraFunc();
}
}
.
.
.
//Base_Class 2
class ShapeExtra
{
public ShapeExtra() {}
}
class CircleExtra : ExtraClass
{
public CircleExtra() {}
void CircleExtraFunc() {//Do stuff}
}
class TriangleExtra : ExtraClass
{
public TriangleExtra() {}
void TriangleExtra() {//Do stuff}
}
.
.
.
因此,我需要将子类中的m_var
保留为自己的唯一版本。因为现在(没有额外的CircleExtra m_var;
),GetVar()
工作,但在CircleFunc
,m_var
仍然是ShapeExtra
类型,因此不知道CircleExtraFunc
存在。每次我想这样做时,我都可以投m_var
,但那是重复的,在我的现实世界中不值得。有没有办法利用基于ShapeExtra
的唯一类中的函数,同时保持GetVar()
函数Shape
?
如果我遗漏了什么,请提问。
简单地使用继承而不使用指针是不可能的,因为C++是一种静态和严格类型的语言。
可以继承变量和函数,但需要强制转换函数返回值。
您还可以重写函数以使其返回具体类型,但随后必须在函数内强制转换变量。
你也可以在子类中声明与具体类相同的 var,但随后你只是在超类中隐藏变量而不继承任何内容。
我宁愿使用模板寻求解决方案。使变量的类型成为模板类型,并使用子类中的具体类型扩展模板。它会完美地工作。
自从我上次在C++编程以来已经有很长时间了,如果以下示例中存在错误,请原谅。我相信你可以很容易地让它工作。
template <class S>
class Shape {
S m_var;
//......
public:
S var () {
return m_var;
}
//.......
}
class Circle: Shape <CircleExtra> {
// var method returns CircleExtra
//......
}
编辑: 关于一些注释,为了允许虚拟调用该方法,可以使用相关的返回类型。类似于以下示例。
class Shape {
public:
virtual ShapeExtra *var () = 0;
}
template <typename SE>
class ConcreteShape: Shape {
public:
virtual SE *var() {
return &m_var;
}
// Constructor, etc.
private:
SE m_var;
}
或者一些变化。现在,具体形状可以从扩展模板中受益,只要 SE * 与 ShapeExtra * 相关(类型参数扩展 ShapeExtra)。并且您可以通过形状接口透明地使用该方法。
使用指针,这是完全可能的。 使用您的示例,您可以执行以下操作:
#include <iostream>
#include <memory>
using namespace std;
//Extras
class ShapeExtra
{
public:
ShapeExtra() {}
void ShapeFunc() { std::cout << "Shape"; }
virtual ~ShapeExtra() = default; //Important!
};
class Shape
{
public:
std::unique_ptr<ShapeExtra> m_var;
//require a pointer on construction
//make sure to document, that Shape class takes ownership and handles deletion
Shape(ShapeExtra* p):m_var(p){}
//The common functions
ShapeExtra& GetVar(){ return *m_var; }
void ShapeFunc() {m_var->ShapeFunc();}
};
class CircleExtra : public ShapeExtra
{
public:
void CircleExtraFunc() {std::cout << "Circle";}
};
class Circle : public Shape
{
CircleExtra* m_var;
public:
Circle() : Shape(new CircleExtra()) {
m_var = static_cast<CircleExtra*>(Shape::m_var.get());
}
void CircleFunc()
{
m_var->CircleExtraFunc();
}
};
int main() {
Circle c;
//use the ShapeExtra Object
c.GetVar().ShapeFunc();
//call via forwarded function
c.ShapeFunc();
//call the circleExtra Function
c.CircleFunc();
return 0;
}
在 ideone 上进行测试
请注意指针和虚拟析构函数的使用:
- 通过在
ShapeExtra
基类中使用虚拟析构函数,可以使用ShapeExtra*
销毁任何派生类的对象。这很重要,因为 - 通过使用
std::unique_ptr<ShapeExtra>
而不是普通的 C 指针,我们确保在销毁Shape
时正确删除对象。 - 记录这种行为可能是一个好主意,即
Shape
拥有ShapeExtra*
的所有权。这尤其意味着,我们不会删除Circle
析构函数中的CirleExtra*
- 我决定在这里要求对构造进行
ShapeExtra*
,但也可以稍后使用std::unique_ptr::reset()
并检查取消引用Shape::m_var
nullptr
构造 - 顺序是这样的:在调用
Circle
的构造函数时,我们首先创建一个新的CircleExtra
,在最后执行Circle
的构造函数之前传递给Shape
。 - 销毁顺序首先
Circle
(最后创建),然后Shape
,这也为我们破坏了ShapeExtra
,包括(通过虚拟功能)CircleExtra
我推荐以下方法:
class ShapeExtra
{
public:
virtual ~ShapeExtra() { }
virtual void SomeCommonShapeFunc() { std::cout << "Shape"; }
};
class Shape
{
public:
virtual ShapeExtra &GetVar() = 0; // Accessor function.
};
请注意,类Shape
根本没有任何数据成员。之后,对于每个派生类,您需要:
class CircleExtra : public ShapeExtra
{
public:
void SomeCommonShapeFunc() { std::cout << "Circle"; }
};
class Circle : public Shape
{
CircleExtra m_var; // Data member with circle specific class.
public:
virtual ShapeExtra &GetVar() { return m_var; }
};
Circle
中虚拟方法的实现将返回对基类ShapeExtra
的引用。这将允许在基类中使用此额外内容。
请注意,根本不使用指针和模板。这简化了整体设计。
- 从类继承时,继承的类是否会通过父类重新定义继承的变量
- 如何在C++子类中访问父类的私有变量
- 从模板化父类中的派生内部类访问受保护的成员变量
- 如何将一个变量用于父类和派生类
- 是否可以在不修改父类的情况下将成员变量初始化推迟到继承的类?
- 将子类实例保存在父类型变量中并通过父变量使用 Child 函数?
- 重写子类构造函数中的父类变量
- 编辑从父类继承的变量
- 父类中的构造函数不会将值分配给私有变量
- 如何在 getter 的父类中初始化变量的情况下访问子类中的变量
- 尝试为所有子类 B 编辑父类 A 类的静态变量
- 删除父类时,方法局部静态变量会发生什么情况
- 有没有更好的方法可以从子类访问父类的变量?
- C++:使用父类运算符函数更新子类对象的继承变量
- 引用子变量的父类
- 访问父类变量
- 子类无法访问父类的变量
- 在C++中,如何从父类变量的子类调用重载方法
- 带模板的继承(访问子类成员函数内父类的变量和对象)
- 如何在继承类中创建父类变量数组作为私有成员