#include <iostream>
#include <string>
#include <typeinfo>
class Person {
std::string name;
Person* bestFriend;
public:
Person (const std::string& newName) : name (newName) {}
virtual ~Person() = default;
std::string getName() const {return name;}
void setName (const std::string& newName) {name = newName;}
Person* getBestFriend() const {return bestFriend;}
void setBestFriend (Person* newBestFriend) {bestFriend = newBestFriend;}
};
class Muslim: public Person {
public:
Muslim (const Person& person) : Person (person) {
// religion = Islam; etc...
}
};
int main() {
Person *mary = new Person ("Mary"), *sandy = new Person ("Sandy");
mary->setBestFriend (sandy);
std::cout << "sandy = " << sandy << ", " << typeid(*sandy).name() << std::endl;
std::cout << mary->getName() << "'s best friend is " << mary->getBestFriend()->
getName() << "." << std::endl;
Muslim* fatima = new Muslim (static_cast<Muslim>(*sandy)); // the big change
fatima->setName ("Fatima"); // should now delete sandy, because fatima takes on every attribue of sandy
std::cout << "fatima = " << fatima << ", " << typeid(*fatima).name() << std::endl;
std::cout << mary->getName() << "'s best friend is " << mary->getBestFriend()->
getName() << "." << std::endl; // still Sandy, of course
}
输出:
sandy = 0x32658,6Person
玛丽最好的朋友是桑迪。
fatima = 0x23fec0,6Muslim
玛丽最好的朋友是桑迪。
当然,我们希望:玛丽最好的朋友是法蒂玛,有玛丽 - > getBestFriend() - &gt; getReligion()==伊斯兰教等...... 如何重新设计整个事物以使其自动化(假设有成千上万的人认识她)?
我想使用继承,因为类穆斯林会对Person方法(以及许多新的数据成员和方法)有许多复杂的覆盖。
答案 0 :(得分:1)
我的第一种方法是,正如@Joseph Mansfield在评论中建议的那样,religion
属性为Person
。因此,更改只会意味着属性的更改而不是新的对象。
尽管如此,如果要为您设置不同的类,则可以使用观察者模式。也就是说,任何一个人的朋友都应该订阅(在朋友地址簿中)列表给人改变。该订户必须实现来自同一接口(订户)的方法,当其属性发生变化时,该方法应由Person
对象调用。
总结一下:
Person
(friends
)为每位朋友提供地址列表。friendChanged(...)
)Person
通过创建新类的新对象而发生更改时,它必须遍历调用friends
的{{1}}列表并向其传递新的人物对象地址。之后,您可以销毁和取消分配旧对象。最后,我不认为宗教应该被表示为一个子类。宗教对我来说是一个人的特征,因此,它应该是一个属性。有一个OOP原则说:Favor composition over inheritance。你的设计似乎是人为地反对这个原则。
答案 1 :(得分:0)
class Person;
class ObserverPersonInterface {
public:
virtual void registerObserver (Person*) = 0;
virtual void removeObserver (Person*) = 0;
virtual void notifyObservers() const = 0;
};
class AddressChangeData : public ObserverPersonInterface {
public:
void addressChange (const Person* oldPerson, Person* newPerson) {
oldAddress = oldPerson;
newAddress = newPerson;
// observers.remove (oldAddress); // but not relevant here
notifyObservers();
}
virtual void registerObserver(Person* person) override {
observers.emplace_back (person);
}
virtual void removeObserver(Person* person) override {
observers.remove (person);
}
private:
virtual inline void notifyObservers() const override;
std::list<Person*> observers; // should perhaps be a red-black tree for greater efficiency
const Person *oldAddress;
Person *newAddress;
} changeOfAddressData;
class Person {
public:
Person() {
changeOfAddressData.registerObserver(this);
}
// every new Person constructed is registered to changeOfAddressData
Person(const std::string& newName) : name (newName) {
changeOfAddressData.registerObserver (this);
}
virtual ~Person() = default;
std::string getName() const {return name;}
void setName (const std::string& newName) {name = newName;}
Person* getBestFriend() const {return bestFriend;}
void setBestFriend (Person* newBestFriend) {bestFriend = newBestFriend;}
protected:
void notifyChangeOfAddress(const Person* oldAddress, Person* newAddress) const {
changeOfAddressData.addressChange (oldAddress, newAddress);
delete oldAddress;
}
private:
std::string name;
Person* bestFriend;
};
class Muslim : public Person {
public:
Muslim() = default;
Muslim(const Person& person) : Person(person) {
changeOfAddressData.registerObserver (this);
notifyChangeOfAddress (&person, this);
}
};
inline void AddressChangeData::notifyObservers() const {
for (Person* x : observers) {
if(x->getBestFriend() == oldAddress) {
x->setBestFriend(newAddress);
}
}
}
int main() {
Person *mary = new Person ("Mary"), *sandy = new Person ("Sandy");
mary->setBestFriend (sandy);
sandy->setBestFriend (mary);
std::cout << "mary = " << mary << ", " << typeid(*mary).name() << std::endl;
std::cout << "sandy = " << sandy << ", " << typeid(*sandy).name() << std::endl;
std::cout << mary->getName() << "'s best friend is " << mary->getBestFriend()->getName() << "." << std::endl;
std::cout << sandy->getName() << "'s best friend is " << sandy->getBestFriend()->getName() << "." << std::endl;
Muslim* fatima = new Muslim(static_cast<Muslim>(*sandy));
// all subscribers of changeOfAddressData notified of sandy's address change, sandy is deleted automatically
fatima->setName("Fatima");
std::cout << "fatima = " << fatima << ", " << typeid(*fatima).name() << std::endl;
std::cout << mary->getName() << "'s best friend is " << mary->getBestFriend()->getName() << "." << std::endl;
std::cout << fatima->getName() << "'s best friend is " << fatima->getBestFriend()->getName() << "." << std::endl;
Muslim* shazia = new Muslim (static_cast<Muslim>(*mary));
// all subscribers of changeOfAddressData notified of mary's address change, mary is deleted automatically
shazia->setName ("Shazia");
std::cout << "shazia = " << shazia << ", " << typeid(*shazia).name() << std::endl;
std::cout << shazia->getName() << "'s best friend is " << shazia->getBestFriend()->getName() << "." << std::endl;
std::cout << fatima->getName() << "'s best friend is " << fatima->getBestFriend()->getName() << "." << std::endl;
std::cin.get();
}