我可以将派生的 class 指向不同的基础吗? (即:更改 child 的家庭)
Can I point a derived class to a different base? (i.e: change the family of a child)
我正在编写一些练习代码来理解 class 继承,但我无法弄清楚是否有办法实现我在标题中试图解释的内容。
所以我想做的就是拥有Family和Member(家庭成员)class。一个家庭可以有多个成员,但成员只能有一个家庭。但是假设其中一位成员结婚了。所以他们正在将他们的家庭从 A 改为其他家庭 B。有没有办法做到这一点?
#include <iostream>
#include <string>
class Family {
std::string _familyName;
public:
Family();
void setFamilyName(std::string& str) { _familyName = str;}
void printFamilyName() {
std::cout << "Family name is: " << _familyName << std::endl;
}
}
class Member : public Family {
std::string _firstName;
public:
Member();
void setFirstName(std::string& str) { _firstName = str;}
void changeFamily(Family *f) {} // What do i do here ?
}
int main(){
Member m;
m.setFamilyName("Smith");
m.setFirstName("John");
m.printFamilyName();
Family f;
B.setFamilyName("Williams");
m.changeFamily(&f);
m.printFamilyName();
return 0;
}
据此,我想得到一个输出
Family name is: Smith
Family name is: Williams
谢谢。
(额外的问题是,有没有办法在不构造family部分的情况下创建成员变量,而是在声明成员的同时将新成员变量绑定到现有的family变量?)
A family can have multiple members but members can have only one family. But let's say one of the members got married. So they are changing their family from A to other family B. Is there a way to do that?
您需要定义对象之间的关系,而不是对象类型。您可以通过使用对象之间的容器包含关系来做到这一点,而不是 class - classes.
之间的派生 class 关系。
struct Member;
struct Family
{
std::vector<Member*> members;
}
struct Member
{
Family* family;
}
我将让您了解如何定义 classes 的成员函数,以便以稳健的方式维护对象之间的关系和对象的生命周期。
简短回答:不。继承是在编译时设置的,您不能在运行时更改它。
但我不认为继承是您要找的东西。 Member
继承了Family
的所有成员和函数。它并不意味着 Member
与 Family
的任何特定实例之间存在关系。这反映在您的设计中 - _familyName
是一个字符串,而不是对对象或其他东西的引用。但是您可以引用其他对象。例如,像这样:
#include <iostream>
#include <string>
#include <vector>
class Family {
std::string _familyName;
public:
Family(std::string name) : _familyName(name) {};
void printFamilyName() {
std::cout << "Family name is: " << _familyName << std::endl;
}
}
class Member {
std::string _firstName;
std::vector<Family*> families;
public:
Member(Family *familyPtr) { addFamily(familyPtr) };
void setFirstName(std::string& str) { _firstName = str;}
void addFamily(Family *familyPtr) { families.push_back(familyPtr) };
void printFamilies() { for (auto &ptr : families) { ptr->printFamilyName() } };
}
int main()
{
Family Jackson("Jackson");
Family Williams("Williams");
Member John(&Jackson);
Member Alice(&Williams);
John.printFamilies();
John.addFamily(&Williams);
John.printFamilies();
return 0;
}
Member
不需要classFamily
的任何函数或值,所以我们不继承它们。相反,我们维护一个指向 Family
对象的指针列表,这个 Member
"belongs" 指向,因此暗示了这个 Member
和 Family
的那些实例之间的关系。当我们想要打印 Member
拥有的所有 Family
对象时,我们只需遍历指针向量并在每个指针上调用 printFamilyName()
。
我认为你不需要继承,你认为继承是不正确的。当处理多个一起工作的 classes 时,无论是一个 class 包含另一个关系还是父子关系,总是有一个问题要问你自己:两个 classes 之间的关系是它是 "Is a relationship" 还是 "Has a relationship"。当您问自己这个问题并且很容易回答时,您应该知道您的 classes 需要什么设计类型。
例如:狗是哺乳动物,狗有爪子。所以如果我们这里有 3 classes。结构看起来像这样:
class Mammal {
/* code */
};
class Dog : public Mammal {
/* code */
};
这里我们有遗传,因为狗是哺乳动物,会继承所有哺乳动物的所有特征!
接下来我们会有这个:
class Paws {
/* code */
};
那么让我们回到我们的 "dog" class
class Dog : public Mammal {
private:
Paws paws; // this is a member of Dog because a Dog HAS PAWS!
};
我希望这可以解决 classes 的基本结构问题!
现在回顾一下您最初的问题,这是我所做的。我制作了一个基本结构来表示 FamilyMember,其中他们都拥有关于彼此的相同信息。我完全提取了姓氏以删除任何依赖项,并且必须检查姓氏是否相同并更新或替换它等。我的代码如下所示:
struct FamilyMember {
std::string firstName_;
unsigned int age_;
char gender_;
FamilyMember() = default;
FamilyMember(const std::string& firstName, unsigned int age, char gender) :
firstName_(firstName),
age_(age),
gender_(gender)
{}
};
class Family {
private:
std::string familyName_;
std::vector<FamilyMember> members_;
public:
Family() = default;
explicit Family(const std::string& familyName) : familyName_( familyName ) {
}
void addMember(FamilyMember& member) {
members_.push_back(member);
}
FamilyMember& getMember(unsigned int idx) {
return members_.at(idx);
}
std::vector<FamilyMember>& getFamily() {
return members_;
}
const std::string& getFamilyName() const { return familyName_; }
};
int main() {
Family Smith("Smith");
FamilyMember John("John", 32, 'M');
FamilyMember Sarah("Sarah", 29, 'F');
FamilyMember Amanda("Amanda", 19, 'F');
Smith.addMember(John);
Smith.addMember(Sarah);
Smith.addMember(Amanda);
std::cout << "Meet the " << Smith.getFamilyName() << "s:\n";
for (auto& m : Smith.getFamily()) {
std::cout << m.firstName_ << " " << Smith.getFamilyName() << " " << m.age_ << " " << m.gender_ << '\n';
}
Family Jones("Jones");
FamilyMember Tom("Tom", 44, 'M');
FamilyMember Mary("Mary", 43, 'F');
FamilyMember Mike("Mike", 21, 'M');
Jones.addMember(Tom);
Jones.addMember(Mary);
Jones.addMember(Mike);
std::cout << "Meet the " << Jones.getFamilyName() << "s:\n";
for (auto& m : Jones.getFamily() ) {
std::cout << m.firstName_ << " " << Jones.getFamilyName() << " " << m.age_ << " " << m.gender_ << '\n';
}
std::cout << "We present to you today the Union between: "
<< Jones.getMember(2).firstName_ << " " << Jones.getFamilyName() << " and "
<< Smith.getMember(2).firstName_ << " " << Smith.getFamilyName() << '\n';
Jones.addMember(Amanda);
std::cout << "We now have Mr. " << Jones.getMember(2).firstName_ << " " << Jones.getFamilyName() << " and "
<< "Mrs. " << Jones.getMember(3).firstName_ << " " << Smith.getFamilyName() << " " << Jones.getFamilyName() << '\n';
return 0;
}
所以从上面的小程序可以看出;我们根本不需要修改姓氏。这样的结构,当"Amanda"嫁给"Mike"。她仍然属于"Smith"家族,但她也加入了"Jones"家族。现在,如果您尝试通过该结构访问她的个人数据,则没有关于她姓氏的信息。您可以检索她的名字、年龄和性别。如果您想要姓氏的信息,您必须从家庭 class 本身检索它,因为它永远不会改变!
我正在编写一些练习代码来理解 class 继承,但我无法弄清楚是否有办法实现我在标题中试图解释的内容。
所以我想做的就是拥有Family和Member(家庭成员)class。一个家庭可以有多个成员,但成员只能有一个家庭。但是假设其中一位成员结婚了。所以他们正在将他们的家庭从 A 改为其他家庭 B。有没有办法做到这一点?
#include <iostream>
#include <string>
class Family {
std::string _familyName;
public:
Family();
void setFamilyName(std::string& str) { _familyName = str;}
void printFamilyName() {
std::cout << "Family name is: " << _familyName << std::endl;
}
}
class Member : public Family {
std::string _firstName;
public:
Member();
void setFirstName(std::string& str) { _firstName = str;}
void changeFamily(Family *f) {} // What do i do here ?
}
int main(){
Member m;
m.setFamilyName("Smith");
m.setFirstName("John");
m.printFamilyName();
Family f;
B.setFamilyName("Williams");
m.changeFamily(&f);
m.printFamilyName();
return 0;
}
据此,我想得到一个输出
Family name is: Smith
Family name is: Williams
谢谢。
(额外的问题是,有没有办法在不构造family部分的情况下创建成员变量,而是在声明成员的同时将新成员变量绑定到现有的family变量?)
A family can have multiple members but members can have only one family. But let's say one of the members got married. So they are changing their family from A to other family B. Is there a way to do that?
您需要定义对象之间的关系,而不是对象类型。您可以通过使用对象之间的容器包含关系来做到这一点,而不是 class - classes.
之间的派生 class 关系。struct Member;
struct Family
{
std::vector<Member*> members;
}
struct Member
{
Family* family;
}
我将让您了解如何定义 classes 的成员函数,以便以稳健的方式维护对象之间的关系和对象的生命周期。
简短回答:不。继承是在编译时设置的,您不能在运行时更改它。
但我不认为继承是您要找的东西。 Member
继承了Family
的所有成员和函数。它并不意味着 Member
与 Family
的任何特定实例之间存在关系。这反映在您的设计中 - _familyName
是一个字符串,而不是对对象或其他东西的引用。但是您可以引用其他对象。例如,像这样:
#include <iostream>
#include <string>
#include <vector>
class Family {
std::string _familyName;
public:
Family(std::string name) : _familyName(name) {};
void printFamilyName() {
std::cout << "Family name is: " << _familyName << std::endl;
}
}
class Member {
std::string _firstName;
std::vector<Family*> families;
public:
Member(Family *familyPtr) { addFamily(familyPtr) };
void setFirstName(std::string& str) { _firstName = str;}
void addFamily(Family *familyPtr) { families.push_back(familyPtr) };
void printFamilies() { for (auto &ptr : families) { ptr->printFamilyName() } };
}
int main()
{
Family Jackson("Jackson");
Family Williams("Williams");
Member John(&Jackson);
Member Alice(&Williams);
John.printFamilies();
John.addFamily(&Williams);
John.printFamilies();
return 0;
}
Member
不需要classFamily
的任何函数或值,所以我们不继承它们。相反,我们维护一个指向 Family
对象的指针列表,这个 Member
"belongs" 指向,因此暗示了这个 Member
和 Family
的那些实例之间的关系。当我们想要打印 Member
拥有的所有 Family
对象时,我们只需遍历指针向量并在每个指针上调用 printFamilyName()
。
我认为你不需要继承,你认为继承是不正确的。当处理多个一起工作的 classes 时,无论是一个 class 包含另一个关系还是父子关系,总是有一个问题要问你自己:两个 classes 之间的关系是它是 "Is a relationship" 还是 "Has a relationship"。当您问自己这个问题并且很容易回答时,您应该知道您的 classes 需要什么设计类型。
例如:狗是哺乳动物,狗有爪子。所以如果我们这里有 3 classes。结构看起来像这样:
class Mammal {
/* code */
};
class Dog : public Mammal {
/* code */
};
这里我们有遗传,因为狗是哺乳动物,会继承所有哺乳动物的所有特征!
接下来我们会有这个:
class Paws {
/* code */
};
那么让我们回到我们的 "dog" class
class Dog : public Mammal {
private:
Paws paws; // this is a member of Dog because a Dog HAS PAWS!
};
我希望这可以解决 classes 的基本结构问题!
现在回顾一下您最初的问题,这是我所做的。我制作了一个基本结构来表示 FamilyMember,其中他们都拥有关于彼此的相同信息。我完全提取了姓氏以删除任何依赖项,并且必须检查姓氏是否相同并更新或替换它等。我的代码如下所示:
struct FamilyMember {
std::string firstName_;
unsigned int age_;
char gender_;
FamilyMember() = default;
FamilyMember(const std::string& firstName, unsigned int age, char gender) :
firstName_(firstName),
age_(age),
gender_(gender)
{}
};
class Family {
private:
std::string familyName_;
std::vector<FamilyMember> members_;
public:
Family() = default;
explicit Family(const std::string& familyName) : familyName_( familyName ) {
}
void addMember(FamilyMember& member) {
members_.push_back(member);
}
FamilyMember& getMember(unsigned int idx) {
return members_.at(idx);
}
std::vector<FamilyMember>& getFamily() {
return members_;
}
const std::string& getFamilyName() const { return familyName_; }
};
int main() {
Family Smith("Smith");
FamilyMember John("John", 32, 'M');
FamilyMember Sarah("Sarah", 29, 'F');
FamilyMember Amanda("Amanda", 19, 'F');
Smith.addMember(John);
Smith.addMember(Sarah);
Smith.addMember(Amanda);
std::cout << "Meet the " << Smith.getFamilyName() << "s:\n";
for (auto& m : Smith.getFamily()) {
std::cout << m.firstName_ << " " << Smith.getFamilyName() << " " << m.age_ << " " << m.gender_ << '\n';
}
Family Jones("Jones");
FamilyMember Tom("Tom", 44, 'M');
FamilyMember Mary("Mary", 43, 'F');
FamilyMember Mike("Mike", 21, 'M');
Jones.addMember(Tom);
Jones.addMember(Mary);
Jones.addMember(Mike);
std::cout << "Meet the " << Jones.getFamilyName() << "s:\n";
for (auto& m : Jones.getFamily() ) {
std::cout << m.firstName_ << " " << Jones.getFamilyName() << " " << m.age_ << " " << m.gender_ << '\n';
}
std::cout << "We present to you today the Union between: "
<< Jones.getMember(2).firstName_ << " " << Jones.getFamilyName() << " and "
<< Smith.getMember(2).firstName_ << " " << Smith.getFamilyName() << '\n';
Jones.addMember(Amanda);
std::cout << "We now have Mr. " << Jones.getMember(2).firstName_ << " " << Jones.getFamilyName() << " and "
<< "Mrs. " << Jones.getMember(3).firstName_ << " " << Smith.getFamilyName() << " " << Jones.getFamilyName() << '\n';
return 0;
}
所以从上面的小程序可以看出;我们根本不需要修改姓氏。这样的结构,当"Amanda"嫁给"Mike"。她仍然属于"Smith"家族,但她也加入了"Jones"家族。现在,如果您尝试通过该结构访问她的个人数据,则没有关于她姓氏的信息。您可以检索她的名字、年龄和性别。如果您想要姓氏的信息,您必须从家庭 class 本身检索它,因为它永远不会改变!