C++友谊/多态类错误

C++ Friendship / Polymorphic Classes Error

本文关键字:错误 多态 友谊 C++      更新时间:2023-10-16

>在C++中,我使用多态类和友谊来建立一个基本的'朋友组'。但是,当我尝试访问班级人的私人年龄功能时,这是班级男孩的朋友,我无法访问它。问题出在哪里?

/* Polymorphic Classes and Class Friendship */
#include <iostream>
class Person{
public:
Person(char* name, int age) : Name(name), Age(age){}
char* Name;
virtual void Speak(void){
std::cout << "I am a person called " << Name << std::endl;
}
virtual ~Person(void){delete this;}
private:
int Age;
};
class Boy : public Person{
friend class Person;
public:
Boy(char* name, int age, Person* Friend) : Person(name, age), MyFriend(Friend){}
void Speak(void){
std::cout << "I am a boy called " << Name << ". My friend " << MyFriend->Name << "'s age is " << MyFriend->Age /* Error here */ << std::endl;
}
~Boy(void){delete this;}
private:
Person* MyFriend;
};
int main(void){
Person* John = new Person("John", 12);
Boy* James = new Boy("James", 14, John);
Boy* Keith = new Boy("Keith", 18, James);
John->Speak();
James->Speak();
John->~Person();
James->~Boy();
Keith->~Boy();
return (0);
}

技术问题:

C++友谊是单向的。

尝试protected授予对派生类的访问权限。

代码审查:

/* Polymorphic Classes and Class Friendship */

最好避免在C++中*/多行注释中使用 C/*...,因为它们不嵌套,并且一些/许多程序员使用它们来注释掉代码以进行调试。

而是优先使用C++//(单行)注释

#include <iostream>

还行。

class Person{
public:

还行。

Person(char* name, int age) : Name(name), Age(age){}

第一个参数应该是char const*。例如,如果没有const,则在使用符合 C++11 的编译器时,您将无法传递文本字符串。

char* Name;

此处的原始指针需要与构造函数形式参数匹配。

实际上,它初始化为构造函数指针参数的简单副本的方式是,它将任何Person实例的生存期限制为实际参数的生存期。

std::string是一个更加灵活和没有问题的选择。

virtual void Speak(void){
std::cout << "I am a person called " << Name << std::endl;
}

由于这个函数不是const的,所以不能在const对象上调用。

此外,void是C主义,C++不好。

在 C 中,它说这个函数不接受任何参数。在C++中,这是不必要的,即void是不必要的措辞。此外,C 甚至没有成员函数。

virtual ~Person(void){delete this;}

同样,void不好。

在这种情况下,delete this是极其不利的。

private:
int Age;

唯一的问题是未能为数据成员应用某些命名约定。例如,像age_(请注意,下划线随后位于末尾),或者像my_agemyAge

};

还行。

class Boy : public Person{

还行。

friend class Person;

毫无意义,因为类Person无法访问此类中的任何内容。

public:
Boy(char* name, int age, Person* Friend) : Person(name, age), MyFriend(Friend){}

同样,应该char const*.或者std::string const&.

void Speak(void){
std::cout << "I am a boy called " << Name << ". My friend " << MyFriend->Name << "'s age is " << MyFriend->Age /* Error here */ << std::endl;
}

在这里,如果编译器支持它,请添加一个override,以便编译器检查您是否确实覆盖了基类函数,例如void Speak() override {

换句话说,放弃不必要的C主义措辞void,但要添加override,这是非常有用的。

~Boy(void){delete this;}

void不好。

在这种情况下,delete this是极其不利的。

private:
Person* MyFriend;

如前所述,这再次限制了Boy实例的生存期。

};

还行。

int main(void){

void不好。

Person* John = new Person("John", 12);
Boy* James = new Boy("James", 14, John);
Boy* Keith = new Boy("Keith", 18, James);
John->Speak();
James->Speak();
John->~Person();

到目前为止还行。

James->~Boy();
Keith->~Boy();

永远不要显式调用析构函数。好吧,一个非常优秀的经验丰富的程序员在使用放置new进行分配时可能会这样做:它在语言中是有原因的。但作为一个初学者,即使有一两年的专业经验,也不要这样做。

return (0);

技术上还可以,但没有必要。 默认情况下,main返回 0。

}

您指定PersonBoy的朋友,但您希望Boy成为Person的朋友。但是,没有必要使用友谊。Boy已经继承了Person因此,如果您将age声明为类protectedBoy可以看到它。