我有一个抽象基类,它对所有派生类强制执行某些操作。除此之外,我还想强制执行特定于派生类中声明的子类的某些其他操作。
以下是一个最小的例子:
class Base {
public:
virtual void init() = 0;
virtual void reset() = 0;
};
class Derived1 : public Base {
class Data {
int *x1;
public:
Data() {
x1 = NULL;
}
void alloc(int num) {
x1 = new int[num];
}
~Data() {
delete[] x1;
x1 = NULL;
}
} data;
public:
void init() { ... }
void reset() { ... }
void resetData() {
data.~Data();
}
};
class Derived2 : public Base {
class Data {
float *x2;
public:
Data() {
x2 = NULL;
}
void alloc(int num) {
x2 = new float[num];
}
~Data() {
delete[] x2;
x2 = NULL;
}
} data;
public:
void init() { ... }
void reset() { ... }
void resetData() {
data.~Data();
}
};在上面的示例中,Base对所有派生类强制执行init()和重置()方法。
除此之外,我还想强制执行所有派生类都具有
resetData(),该方法称为Data &getData(),用于引用变量G 210
实现这一目标的最佳途径是什么?
发布于 2012-04-19 07:43:23
谢谢你的答复。这就是我想出来的。我知道我违背了最初的要求,即数据必须是派生类的子类,但是下面的设计模式确保所有派生类都有一个data成员变量,每个成员变量的类型不同,但同样,每个派生类都有一些基本方法强制执行。我认为这就是@emsr在他的评论中所建议的。
现在,resetData()是在一个单独的方法中完成的。感谢@LuchianGrigore指出了显式调用析构函数可能存在的问题。现在,这个方法显式地代替了。虚拟析构函数也将调用相同的函数。我知道我不应该从析构函数调用虚拟函数,但是通过显式设置函数的范围,我希望在这里避免任何模糊。(或者这也是个问题?)
struct Data {
virtual void resetData() = 0;
virtual ~Data() {}
};
template<typename _DT>
class Base {
protected:
_DT data;
public:
_DT &getData() {
return data;
}
void resetData() {
data.resetData();
}
virtual void init() = 0;
virtual void reset() = 0;
};
struct Data1 : public Data {
int *x;
Data1() {
x = NULL;
}
void alloc(int num) {
x = new int[num];
}
virtual void resetData() {
delete[] x;
x = NULL;
}
virtual ~Data1() {
Data1::resetData();
}
};
class Derived : public Base<Data1> {
public:
virtual void init() {
// Carry out other init operations
Data1 &x = getData();
x.alloc(10);
}
virtual void reset() {
// Carry out other reset operations
data.resetData();
}
};发布于 2012-04-18 17:13:34
的引用。
在我看来,如果这些在所有派生类中都是常见的,那么您需要在基类中使用它们。
class Base {
public:
Data data;
void resetData(); //if data is not a pointer, are you sure you want
//to call its destructor?
//this will lead to undefined behavior when
//Base is destroyed, as data will automatically
//be freed
Data& getData();
virtual void init() = 0;
virtual void reset() = 0;
};你的课仍然是抽象的,以防万一这是个问题。
没有这种方法的
getData的H 222f 223从设计的角度来看,所有这些都应该在基类中。
发布于 2012-04-18 19:28:17
我将在数据类型上模板基类,并将数据定义移出派生类。缺点是,您不再有一个单一类型的基础。
template <class Data>
class Base {
public:
virtual ~Base() {}
virtual void init() = 0;
virtual void reset() = 0;
virtual Data& getData() {
return data;
}
virtual void resetData() {
data.reset();
}
protected:
Data data;
};
class Data1 {
int *x1;
public:
Data1() {
x1 = 0;
}
void alloc(int num) {
x1 = new int[num];
}
void reset() {
delete[] x1;
x1 = 0;
}
~Data1() {
delete[] x1;
x1 = 0;
}
};
class Derived1 : public Base<Data1> {
public:
public:
void init() { }
void reset() { }
};
class Data2 {
float *x2;
public:
Data2() {
x2 = 0;
}
void reset() {
delete[] x2;
x2 = 0;
}
void alloc(int num) {
x2 = new float[num];
}
~Data2() {
delete[] x2;
x2 = 0;
}
};
class Derived2 : public Base<Data2> {
public:
public:
void init() { }
void reset() { }
Data2& getData() {
return data;
}
void resetData() {
data.reset();
}
};另一种方法是从单个基类继承数据类。在这种情况下,您将无法强制成员变量的名称是数据。
class IData {
public:
virtual ~IData() {}
virtual void reset() = 0;
};
class Base {
public:
virtual ~Base() {}
virtual void init() = 0;
virtual void reset() = 0;
virtual IData& getData() = 0;
virtual void resetData() = 0;
};
class Derived1 : public Base {
class Data : public IData {
int *x1;
public:
Data() {
x1 = 0;
}
void alloc(int num) {
x1 = new int[num];
}
void reset() {
delete[] x1;
x1 = 0;
}
~Data() {
delete[] x1;
x1 = 0;
}
} data;
public:
void init() { }
void reset() { }
IData& getData() {
return data;
}
void resetData() {
data.reset();
}
};
class Derived2 : public Base {
class Data : public IData {
float *x2;
public:
Data() {
x2 = 0;
}
void reset() {
delete[] x2;
x2 = 0;
}
void alloc(int num) {
x2 = new float[num];
}
~Data() {
delete[] x2;
x2 = 0;
}
} data;
public:
void init() { }
void reset() { }
IData& getData() {
return data;
}
void resetData() {
data.reset();
}
};https://stackoverflow.com/questions/10214443
复制相似问题