在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);
}
答案 0 :(得分: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*
。例如,在使用符合C ++ 11的编译器时,如果没有const
,则无法传递文字字符串。
char* Name;
这里的原始指针需要匹配构造函数形式参数。
实际上,它被初始化为构造函数指针参数的简单副本的方式,它将任何Person
实例的生命周期限制为实际参数的生命周期。
std::string
是一种更灵活,更无问题的选择。
virtual void Speak(void){
std::cout << "I am a person called " << Name << std::endl;
}
由于此函数不是const
,因此无法在const
对象上调用它。
此外,void
是C-ism,在C ++中是非常好的。
在C中它表示此函数不带任何参数。在C ++中,这是不必要的,即void
是不必要的措辞。此外,C甚至没有会员功能。
virtual ~Person(void){delete this;}
同样,void
是不合时宜的。
delete this
在这种背景下非常不合适。
private:
int Age;
唯一的问题是未能为数据成员应用某些命名约定。例如,如age_
(请注意,下划线位于结束),或类似my_age
或myAge
。
};
行。
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 {
。
换句话说,抛弃void
这是不必要的C-ism措辞,但确实添加了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.
}
答案 1 :(得分:0)
您已指定Person
是Boy
的朋友,但您希望Boy
成为Person
的朋友。但是没有必要使用友谊。 Boy
已经继承了Person
,因此如果您将age
声明为protected
,则Boy
可以看到它。