C++ 像C++;设计模式以避免指针?
我有一个如下例所示的类层次结构,C++ 像C++;设计模式以避免指针?,c++,design-patterns,pointers,C++,Design Patterns,Pointers,我有一个如下例所示的类层次结构,State包含一个ZipCodes列表和一个Citys列表,每个列表都包含指向ZipCodes的指针 #include <iostream> #include <vector> #include <boost/shared_ptr.hpp> using namespace std; /** * Zone Improvement Plan (ZIP) code */ class ZipCode { public:
State
包含一个ZipCode
s列表和一个City
s列表,每个列表都包含指向ZipCode
s的指针
#include <iostream>
#include <vector>
#include <boost/shared_ptr.hpp>
using namespace std;
/**
* Zone Improvement Plan (ZIP) code
*/
class ZipCode {
public:
ZipCode() : code_(0), plus4_(0) {}
ZipCode(int code, int plus4 = 0) : code_(code), plus4_(plus4) {}
virtual ~ZipCode() {};
int code() const { return code_; }
int plus4() const { return plus4_; }
void set_code(int code) { code_ = code; }
void set_plus4(int plus4) { plus4_ = plus4; }
private:
int code_;
int plus4_;
};
typedef boost::shared_ptr<ZipCode> ZipPtr;
/**
* City points to one or more zip codes
*/
class City {
public:
const vector<ZipPtr>& zip() const { return zip_; }
void add_zip_ptr(const ZipPtr x) { if (x != NULL) zip_.push_back(x); }
private:
// TODO: this vector should be a hash set
vector<ZipPtr> zip_;
};
/**
* State contains cities, each of which has pointers to
* zip codes within the state.
*/
class State {
public:
const vector<City>& city() const { return city_; }
const vector<ZipPtr>& zip() const { return zip_; }
const ZipPtr zip_of(int code) const {
for (size_t i = 0; i < zip_.size(); i++) {
if (zip_[i]->code() == code) {
return zip_[i];
}
}
return ZipPtr();
}
void add_city(const City& x) { city_.push_back(x); }
void add_zip(int code) { zip_.push_back(ZipPtr(new ZipCode(code))); }
private:
// TODO: these vectors should be hash sets
vector<City> city_;
vector<ZipPtr> zip_;
};
int main() {
State texas;
City dallas, houston;
// create state ZIPs
texas.add_zip(75380);
texas.add_zip(75381);
texas.add_zip(77219);
texas.add_zip(77220);
// point city ZIPs to the ones we just created
dallas.add_zip_ptr(texas.zip_of(75380));
dallas.add_zip_ptr(texas.zip_of(75381));
houston.add_zip_ptr(texas.zip_of(77219));
houston.add_zip_ptr(texas.zip_of(77220));
// print all ZIPs
cout << "ZIPs in Texas: " << endl;
const vector<ZipPtr>& zips = texas.zip();
for (size_t i = 0; i < zips.size(); i++) {
cout << " " << zips[i]->code() << endl;
}
cout << "ZIPs in Dallas, Texas: " << endl;
const vector<ZipPtr> zip_ptrs1 = dallas.zip();
for (size_t i = 0; i < zip_ptrs1.size(); i++) {
cout << " " << zip_ptrs1[i]->code() << endl;
}
cout << "ZIPs in Houston, Texas: " << endl;
const vector<ZipPtr> zip_ptrs2 = houston.zip();
for (size_t i = 0; i < zip_ptrs2.size(); i++) {
cout << " " << zip_ptrs2[i]->code() << endl;
}
// change a state ZIP...
cout << "Changing Houston's ZIP 77220..." << endl;
ZipPtr z = texas.zip_of(77220);
if (z != NULL) z->set_code(88888);
// ...and show the ZIPs of the affected city
cout << "ZIPs in Houston, Texas: " << endl;
const vector<ZipPtr> zip_ptrs3 = houston.zip();
for (size_t i = 0; i < zip_ptrs3.size(); i++) {
cout << " " << zip_ptrs3[i]->code() << endl;
}
return 0;
}
目标是能够更新ZipCode
s,而无需更新City
s(或创建City
的新实例)
<>下面的C++代码符合这个要求,但是它使用指针,我宁愿避免,因为strong>如何重新设计这个[naive]实现,使其不依赖指针?感谢您的帮助
编辑:更新下面的代码以使用boost::shared_ptr
而不是原始指针。请注意,State
、City
和ZipCode
只是一些示例名称,它们都是糟糕的选择名称(我可以选择“A”、“B”和“C”),因为实际代码允许相当于City
的人共享ZipCode
s
#include <iostream>
#include <vector>
#include <boost/shared_ptr.hpp>
using namespace std;
/**
* Zone Improvement Plan (ZIP) code
*/
class ZipCode {
public:
ZipCode() : code_(0), plus4_(0) {}
ZipCode(int code, int plus4 = 0) : code_(code), plus4_(plus4) {}
virtual ~ZipCode() {};
int code() const { return code_; }
int plus4() const { return plus4_; }
void set_code(int code) { code_ = code; }
void set_plus4(int plus4) { plus4_ = plus4; }
private:
int code_;
int plus4_;
};
typedef boost::shared_ptr<ZipCode> ZipPtr;
/**
* City points to one or more zip codes
*/
class City {
public:
const vector<ZipPtr>& zip() const { return zip_; }
void add_zip_ptr(const ZipPtr x) { if (x != NULL) zip_.push_back(x); }
private:
// TODO: this vector should be a hash set
vector<ZipPtr> zip_;
};
/**
* State contains cities, each of which has pointers to
* zip codes within the state.
*/
class State {
public:
const vector<City>& city() const { return city_; }
const vector<ZipPtr>& zip() const { return zip_; }
const ZipPtr zip_of(int code) const {
for (size_t i = 0; i < zip_.size(); i++) {
if (zip_[i]->code() == code) {
return zip_[i];
}
}
return ZipPtr();
}
void add_city(const City& x) { city_.push_back(x); }
void add_zip(int code) { zip_.push_back(ZipPtr(new ZipCode(code))); }
private:
// TODO: these vectors should be hash sets
vector<City> city_;
vector<ZipPtr> zip_;
};
int main() {
State texas;
City dallas, houston;
// create state ZIPs
texas.add_zip(75380);
texas.add_zip(75381);
texas.add_zip(77219);
texas.add_zip(77220);
// point city ZIPs to the ones we just created
dallas.add_zip_ptr(texas.zip_of(75380));
dallas.add_zip_ptr(texas.zip_of(75381));
houston.add_zip_ptr(texas.zip_of(77219));
houston.add_zip_ptr(texas.zip_of(77220));
// print all ZIPs
cout << "ZIPs in Texas: " << endl;
const vector<ZipPtr>& zips = texas.zip();
for (size_t i = 0; i < zips.size(); i++) {
cout << " " << zips[i]->code() << endl;
}
cout << "ZIPs in Dallas, Texas: " << endl;
const vector<ZipPtr> zip_ptrs1 = dallas.zip();
for (size_t i = 0; i < zip_ptrs1.size(); i++) {
cout << " " << zip_ptrs1[i]->code() << endl;
}
cout << "ZIPs in Houston, Texas: " << endl;
const vector<ZipPtr> zip_ptrs2 = houston.zip();
for (size_t i = 0; i < zip_ptrs2.size(); i++) {
cout << " " << zip_ptrs2[i]->code() << endl;
}
// change a state ZIP...
cout << "Changing Houston's ZIP 77220..." << endl;
ZipPtr z = texas.zip_of(77220);
if (z != NULL) z->set_code(88888);
// ...and show the ZIPs of the affected city
cout << "ZIPs in Houston, Texas: " << endl;
const vector<ZipPtr> zip_ptrs3 = houston.zip();
for (size_t i = 0; i < zip_ptrs3.size(); i++) {
cout << " " << zip_ptrs3[i]->code() << endl;
}
return 0;
}
#包括
#包括
#包括
使用名称空间std;
/**
*区域改进计划(邮政编码)
*/
类ZipCode{
公众:
ZipCode():代码_0,plus4_0{}
ZipCode(int-code,int-plus4=0):code(code),plus4(plus4){
虚拟~ZipCode(){};
int code()常量{返回代码}
int plus4()常量{返回plus4;}
无效集合_码(int码){code_u=code;}
空集_plus4(int plus4){plus4_=plus4;}
私人:
int代码u3;;
整数加4;
};
typedef boost::shared_ptr ZipPtr;
/**
*城市指向一个或多个邮政编码
*/
阶级城市{
公众:
常量向量&zip()常量{return zip}
void add_zip_ptr(const zip tr x){if(x!=NULL)zip_u.push_back(x)}
私人:
//TODO:此向量应为哈希集
矢量压缩编码;
};
/**
*州包含城市,每个城市都有指向城市的指针
*州内的邮政编码。
*/
阶级国家{
公众:
常量向量&city()常量{返回城市}
常量向量&zip()常量{return zip}
常量ZipPtr zip_of(整数代码)常量{
对于(大小i=0;icode()==code){
返回邮政编码[i];
}
}
返回ZipPtr();
}
void add_city(const city&x){city_.push_back(x)}
void add_zip(int code){zip_u.push_back(ziptr(new ZipCode(code));}
私人:
//TODO:这些向量应该是散列集
矢量城市;
矢量压缩编码;
};
int main(){
德克萨斯州;
休斯敦达拉斯市;
//创建状态拉链
德克萨斯州。增加邮政编码(75380);
德克萨斯州。增加邮政编码(75381);
德克萨斯州。增加邮政编码(77219);
德克萨斯州。增加邮政编码(77220);
//point city将拉链拉到我们刚刚创建的位置
达拉斯。增加(德克萨斯州,邮编:75380));
达拉斯,增加了(德克萨斯州,邮编75381));
休斯顿。增加(德克萨斯州,邮编:77219));
休斯顿,增加了(德克萨斯州,邮编:77220));
//打印所有拉链
cout除非您想复制ZipCode对象,否则您属于这类用法(如中所述):
Bar实例实际上是被管理的
通过你程序的其他部分,
而Foo类只需要
能够访问它
这似乎是合法的使用
但是,您可能需要考虑复制选项(如果向量必须重新分配其数据,以永久避免问题),或者从其<代码>城市< /代码>中生成<代码>状态>代码>聚合>代码> ZIPCOD/<代码>,而不是分发它们:代码> ZIPCOND/<代码> .<
该副本只是暗示您停止在City
中使用指针。聚合ZipCodes
意味着不给State一个ZipCodes
列表,而是给City
一个ZipCode
实例列表,当调用zip\u of
时,您将遍历城市并迭代t通过他们的ZipCode
集合。我将这种情况视为两种1:n关系
州:城市==1:n
城市:Zipcode
==1:n
基于此,我认为状态
包含
vector<ZipCode> zip_;
vector-zip;
声音不好
我可以
class State {
vector< City > cities_in_state_;
};
class City {
vector< Zipcode > zips_in_city_;
};
类状态{
向量<城市>处于城市状态的城市;
};
阶级城市{
矢量zips\u在城市中;
};
这不需要指针。编写的代码不正确:当您将城市或邮政编码添加到州时,向量可能需要重新分配自身,此时指向现有城市和邮政编码的所有指针都将无效(因为城市和邮政编码对象将移到内存中的其他位置)@James,谢谢你指出这个bug。我必须编辑一下,因为你的主题是关于避免指针编程范例,这可能会引起你的兴趣:(我喜欢这个吸引人的名字。)我不认为它是完全全面的,但这只是一个开始:)好的,谢谢。实际上,州
,城市
,和ZipCode
是一个坏例子(我的坏例子)在我的实际代码中,等价于<代码>锡蒂>代码>共享代码> >代码> >代码>。如果我改变了代码>锡蒂<代码>聚合>代码> ZIPCOD/<代码> s,则可以在代码< >代码>状态>代码>中重复复制<代码>代码> <代码> s。@与C++共享的正确方法是指针或引用。 >或代码> STD::UNIQUYGPTR <代码>,从C++ 0xSTL到帮助。在短时间内,我没有足够的C++来使用它,但是如果C++没有选择,Boost可能也有同样的值。Boosi::SyrdYpPTR看起来很有前途…谢谢。我可能只是用ITI同意您对我的例子中的1:N的评论。(而且@zneak实际上也发表了同样的评论)。我试图选择一个比实际公司专有代码更容易理解的实际示例(在这种情况下,这些类关系是有意义的),但我显然失败了:-\