C++ 利用值类型和引用的统一语法
假设我们有以下C++ 利用值类型和引用的统一语法,c++,inheritance,design-patterns,C++,Inheritance,Design Patterns,假设我们有以下Base类和两个派生类Derived1和Derived2: class Base { // Some declarations ... }; class Derived1 : public Base { // Some declarations ... public: vector<int> _array; }; class Derived2 : public Base { // Some declarations ... public: vector<
Base
类和两个派生类Derived1
和Derived2
:
class Base {
// Some declarations ...
};
class Derived1 : public Base {
// Some declarations ...
public:
vector<int> _array;
};
class Derived2 : public Base {
// Some declarations ...
public:
vector<int> &_array;
};
在Base
中使用名为index
的纯虚拟函数是一种解决方案。但是,在这种情况下,我们需要在两个派生类中使用相同的int-index(uint x){return_-array[x];}
实现。这很难看,我们无法在Base
中实现该函数,因为它不知道\u array
因此,我们必须(1)将\u数组
的类型更改为相同的类型(例如,更改为向量*
),并在基
中实现索引
,或者(2)在派生1
和派生
中实现两种实现,以便使用公共接口。但是,我负担不起(1),因为它会在Derived1
中添加一个额外的间接层,如果可能的话,我希望避免这种情况。拥有大量这样的成员变量会让(2)变得可怕,因为这需要大量的样板文件和复制,而且很难维护
我知道这两个索引
函数实际上是不同的函数,因为它们在不同的类型上运行。在许多其他场景中,Derived1
和Derived2
需要单独的函数,因为它们具有不同的行为(并将编译为不同的目标代码)。然而,在C++的情况下,实现方式在语法上是相似的,所以我想知道是否有办法利用这个。
一种可能的解决方案是使用自由函数:
template <class T>
int index(const T &obj, uint x) {
return obj._array[x];
}
模板
整数索引(常数T&obj,单位x){
返回对象数组[x];
}
在这里,我们宣布index
是Derived1
和Derived2
的朋友。然而,这可能并不优雅,因为它使用了一个朋友声明(两次声明朋友也是重复的)
因此,我的问题是:
是否有更优雅的方法来实现索引
,同时避免性能成本和代码重复
附录:
CRTP与我想要的非常接近,但它在删除现有类型Base
时引入了两个新类型(Base
是第一个,而Base
是第二个)。这样的重构会在代码库中引发更多的变化,这是不可取的(例如制作使用Base
模板函数/类的函数/类,甚至将它们从头文件移动到源文件)。理想情况下,我想要的不需要对代码库的其余部分进行更改。使用
模板
类别CrtpBase:公共B
{
公众:
int index(size_t ind){return static_cast(this)->_array[ind];}
};
结构Derived1:公共CrtpBase
{
向量_数组={1,2,3};
};
struct Derived2:公共CrtpBase
{
向量_arr={4,5,6};
向量和数组=\u arr;
};
.我可以说您正在寻找一些设计模式吗?因为有一个标签[design patterns],这可能非常适合类
Base
。谢谢!然而,这完全删除了Base
,但我想要的只是更改现有API的实现(为问题添加了更多的解释)。@loudandclear编辑的更改如何?您仍然可以保持基本状态
CrtpBase
只允许您将此功能添加到派生的
s中。哦,我明白了,不过缺少了一些功能。我认为CrtpBase应该是从B派生的,那么它就有意义了。是这样吗?
template <class T>
int index(const T &obj, uint x) {
return obj._array[x];
}
template <typename D, typename B = Base>
class CrtpBase : public B
{
public:
int index(size_t ind){return static_cast<D*>(this)->_array[ind];}
};
struct Derived1 : public CrtpBase<Derived1>
{
vector<int> _array = {1,2,3};
};
struct Derived2 : public CrtpBase<Derived2>
{
vector<int> _arr = {4,5,6};
vector<int>& _array = _arr;
};