我的程序中存在设计问题,因为我需要偶尔访问属性&子类的方法,它们都存储在基类指针的向量中。我的代码看起来像这样:
class B1;
class B2;
class Base {
private:
int id, a, b;
public:
virtual int getA() { return a; }
virtual int getB() { return b; }
virtual B1 *getB1() { return NULL; } //seems like a bad idea
virtual B2 *getB2() { return NULL; } //to have these two functions
Base(int newId) { id = newId; }
};
class B1 : public Base {
private:
int x;
public:
int getX() { return x; }
B1 *getB1() { return this; }
};
class B2 : public Base {
private:
int y;
public:
int getY() { return y; }
B2 *getB2() { return this; }
};
class Thing {
private:
std::vector<Base*> bases;
void addBase(Base *base) { bases.push_back(base); }
void doB1Stuff();
void doB2Stuff();
void setAandB(int ID, int newA, int newB); //set a and b of one of the elements in bases vector based upon the id given
};
问题是我是否需要在Thing中访问x或y,如下所示:
void Thing::doB1Stuff() {
for(std::vector<Base*>::iterator it = bases.begin(); it != bases.end(); ++it) {
if (it->getB1()) {
//do stuff with b1
}
}
}
上面的代码应该可以工作,但如果它看起来不错,因为在使用这样的B1 / B2属性之前,很容易忘记检查指针是否为空:
void Thing::doB2Stuff() {
for(std::vector<Base*>::iterator it = bases.begin(); it != bases.end(); ++it) {
std::cout << it->getY(); //I believe this will crash the program if a NULL pointer is returned
}
}
我的问题是:访问子类属性的好方法是什么?我想在Thing中有两个单独的B1s和B2s向量,但这似乎不是一个好主意,因为我需要能够轻松设置a和b。有什么想法吗?
答案 0 :(得分:1)
你所拥有的完全没问题:只要你不在NULL
指针向量中存储bases
,就不需要对从迭代器返回的值进行空值检查。不幸的是,指针向量是多态对象容器的唯一选择。你可以创建一个共享指针的向量来简化处理删除,但基本的想法将保持不变。
答案 1 :(得分:0)
您可以检查您正在访问的项目是否是您正在寻找的正确的子类类型,尽管如此,您还需要包含运行时类型信息(rtti)。
然后,如果它是某种类型且不为null,则可以将其强制转换为该类型并调用正确的函数。
此外,您可以使用dynamic _ cast,但为此,您需要再次使用rtti,它与检查自己然后静态转换基本相同。
答案 2 :(得分:0)
你是对的,这不是一个解决问题的好方法,你可以使用dynamic_cast
来安全地确定使用哪个对象,但这对我来说是不好的代码味道。
我要做的是访问子属性,而是创建一个虚函数,返回Base类中所需的值。
示例:
class Base {
private:
int id, a, b;
public:
virtual int getA() { return a; }
virtual int getB() { return b; }
virtual int getSubValue() = 0; //
Base(int newId) { id = newId; }
};
class B1 : public Base {
private:
int x;
public:
int getSubValue() { return x; }
};
class B2 : public Base {
private:
int y;
public:
int getSubValue() { return y; }
};
然后你可以调用它 - &gt; getSubValue()来获取你请求的子值。
这是我的观点,有很多方法可以解决这个问题,但这是我根据您提供的信息提出的建议。