鱼C论坛

 找回密码
 立即注册
查看: 2446|回复: 10

C++一个情人类,如何避免搞基和拉拉

[复制链接]
发表于 2016-3-23 22:41:31 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
[code]#include<iostream>

class Lover {
        public:
                void kiss(Lover lover);//亲谁        
        protected:
                std::string name;
};
class Boyfriend :public Lover{
        public:       
                Boyfriend();
        protected:
                std::string sex;
};
class Girlfriend :public Lover{
        public:
                Girlfriend();
        protected:
                std::string sex;
};
void Lover::kiss(Lover lover){
        std::cout<<"我亲了"<<lover.name ;
}
Boyfriend ::Boyfriend(){
        name="小明";
        sex="男";
}
Girlfriend::Girlfriend(){
        name="小花";
        sex="女";
}

int main(){
        Boyfriend boy;
        Girlfriend girl;
    boy.kiss(girl);
    girl.kiss(boy);
}


这样定义的话我们可以让男的亲男的,女的亲女的不是吗,可我要避免搞基和拉拉,于是我尝试了下面方法
我把 kiss( ) 分别设在Boyfriend 和Girlfriend 里,  void kiss(Girlfriend girl);  void kiss(Boyfriend boy)
让他们只能亲异性,然而这样子编译器提示是未申明 Girlfrien Boyfriend  就是在Boyfriend 里提示为未声明Girlfriend 不认识Girlfriend
在Girlfriend里不认识Boyfriend   
于是我又让他们是友元函数
然而还是未声明不认识
请问有没有办法让他们认识啊
我觉得肯定有方法的啊,肯定可以限制我传入的对象是什么的- -
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-3-24 12:44:56 | 显示全部楼层
本帖最后由 muyu0096 于 2016-3-24 12:49 编辑

首先,你应该在自己运行下源程序,你会发现,你写的代码已经满足你的要求了。你后来加的是画蛇添足。
你之所以产生你的想法是因为你没有理解公用继承的is-a关系。即:子类是一个父类。
对boy.kiss(girl);   girl对象也是基类Lover类的对象,且你调用的成员变量name是基类的成员。所以该函数就是一个基类的方法,被boy子类继承,调用的基类的对象girl(更确切的说是girl的基类部分)的保护成员name。
一般通过引用或者指针作为参数,而不是用对象名,这是因为为了动态指出函数对象(虚函数),也是为了节省系统开销,当然这里用对象做参数也不为错。

其次,就算按你的方法改,这时基类的kiss方法被子类的覆盖。你出错不是出错在友元上,而是你在 定义 void Boyfriend::kiss(Girlfriend girl)时,Girlfriend既没有定义,也没有声明;因此,编译器不知道Girlfriend是一个什么类型。解决方法是在Boyfriend类定义之前,前置声明Girlfriend类。

第三,按照第二中做了以后,问题依旧没有解决,因为name是基类的保护成员,所以,无法通过对象或者指针在类外访问,这里,虽然boy类是lover类的公用继承,可以在类里访问lover类的保护成员,但这种访问是直接访问,比如在boy类里直接cout<<name,但通过对象或者指针访问,实际上就是类外访问了,所以解决办法是把name声明为public,但这失去了保护数据的意义了。

第一帖,回答的够详细吧。。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-3-24 14:45:47 | 显示全部楼层
muyu0096 发表于 2016-3-24 12:44
首先,你应该在自己运行下源程序,你会发现,你写的代码已经满足你的要求了。你后来加的是画蛇添足。
你 ...

嗯,够详细,可是要实现我boy只能亲girl该怎么解决
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-3-24 14:48:50 | 显示全部楼层
奥古斯丁少爷 发表于 2016-3-24 14:45
嗯,够详细,可是要实现我boy只能亲girl该怎么解决

我提的方法不行了,毕竟在BOY类前申明了Girl类,但我Girl类还是会认为Boy类还未申明,同时把name改为public也不好
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-3-24 15:10:42 | 显示全部楼层
同样的,前置声明,如果你不愿意把name声明成public,可以用方法做接口,比如,定义一个成员方法:
string Boyfriend::getName(){return name;};并把方法声明为public。
但这样做,会导致无法相互调用,你在boy类里,可以定义一个 void Boyfriend::kiss(Girlfriend & girl){cout<<"kiss "<<girl.getName();};,但这需要提前知道Girlfriend类的getName方法而不仅仅是光声明有Girlfriend类。因此Girlfriend类的定义必须在定义void Boyfriend::kiss()方法之前,而kiss方法是boy类的类方法成员,所以Girlfriend类要定义在boyfriend类之前。
但如果在Girlfriend类里要同样定义一个类似的kiss方法,那么按照上面的要求,必须要求boy类定义在Girlfriend类之前,
而这是相互矛盾的,而且c++是不允许重复定义的,所以这样的任务无法完成。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-3-24 15:55:37 | 显示全部楼层
muyu0096 发表于 2016-3-24 15:10
同样的,前置声明,如果你不愿意把name声明成public,可以用方法做接口,比如,定义一个成员方法:
string ...

哎,竟然无法实现,虽然觉得不能实现的话以后万一要类似这种效果的怎么办,谢谢啦、
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-3-24 16:53:34 | 显示全部楼层
奥古斯丁少爷 发表于 2016-3-24 15:55
哎,竟然无法实现,虽然觉得不能实现的话以后万一要类似这种效果的怎么办,谢谢啦、

恩,从你的原意来看,这是实现不了,至少我的水平实现不了
不过,这也不正说明了你的题目么。。。搞基和拉拉,是防止不了的。。。。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-3-25 14:53:51 | 显示全部楼层

#include<iostream>

class Lover {
        public:
              virtual  void kiss(Lover lover);//亲谁         
        protected:
                std::string name;
};
class Girlfriend;
class Boyfriend :public Lover{
        public:      
                friend class Girlfriend;
                void kiss(Girlfriend *girl);
                Boyfriend();
        protected:
                std::string sex;
};
class Girlfriend :public Lover{
        public:
                friend void Boyfriend ::kiss(Girlfriend *girl);
                void kiss(Boyfriend *boy);
                Girlfriend();
        protected:
                std::string sex;
};
void Lover::kiss(Lover lover){
        std::cout<<"我亲了"<<lover.name ;
}
Boyfriend ::Boyfriend(){
        name="小明";
        sex="男";
}
Girlfriend::Girlfriend(){
        name="小花";
        sex="女";
}
void Boyfriend::kiss(Girlfriend *girl){
        std::cout<<"我亲了"<<girl->name;
}
void Girlfriend::kiss(Boyfriend *boy){
         std::cout<<"我亲了"<<boy->name;
}

int main(){
        Boyfriend boy;
        Girlfriend girl;
    boy.kiss(&girl);
    girl.kiss(&boy);
}


朋友,我实现我要的效果了,
在BOY类前先用class Girlfriend 申明一次,BOY类知道有Girl类了
同时Girlfriend类的定义在boy类后面    所以可以了
但是有个地方要注意,BOY类里我把Girl类整个作为友元类,而Girl类里我只把boy类的kiss函数作为友元函数,因为我就这一个函数需要访问BOY类的成员数据,并不需要访问Boy类的所有数据,这样有安全一点吧。 但是在BOY类里只能把Girl整个类作为友元类了,而不能把Girl类里的kiss作为友元函数,因为Boy类只知道有Girl类,但是是不知道Girl类里有这个KISS函数的,因为我们的Girl 的kiss函数是在Boy类的后面。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-3-25 14:54:39 | 显示全部楼层
muyu0096 发表于 2016-3-24 15:10
同样的,前置声明,如果你不愿意把name声明成public,可以用方法做接口,比如,定义一个成员方法:
string ...

#include<iostream>

class Lover {
        public:
              virtual  void kiss(Lover lover);//亲谁         
        protected:
                std::string name;
};
class Girlfriend;
class Boyfriend :public Lover{
        public:      
                friend class Girlfriend;
                void kiss(Girlfriend *girl);
                Boyfriend();
        protected:
                std::string sex;
};
class Girlfriend :public Lover{
        public:
                friend void Boyfriend ::kiss(Girlfriend *girl);
                void kiss(Boyfriend *boy);
                Girlfriend();
        protected:
                std::string sex;
};
void Lover::kiss(Lover lover){
        std::cout<<"我亲了"<<lover.name ;
}
Boyfriend ::Boyfriend(){
        name="小明";
        sex="男";
}
Girlfriend::Girlfriend(){
        name="小花";
        sex="女";
}
void Boyfriend::kiss(Girlfriend *girl){
        std::cout<<"我亲了"<<girl->name;
}
void Girlfriend::kiss(Boyfriend *boy){
         std::cout<<"我亲了"<<boy->name;
}

int main(){
        Boyfriend boy;
        Girlfriend girl;
    boy.kiss(&girl);
    girl.kiss(&boy);
}


朋友,我实现我要的效果了,
在BOY类前先用class Girlfriend 申明一次,BOY类知道有Girl类了
同时Girlfriend类的定义在boy类后面    所以可以了
但是有个地方要注意,BOY类里我把Girl类整个作为友元类,而Girl类里我只把boy类的kiss函数作为友元函数,因为我就这一个函数需要访问BOY类的成员数据,并不需要访问Boy类的所有数据,这样有安全一点吧。 但是在BOY类里只能把Girl整个类作为友元类了,而不能把Girl类里的kiss作为友元函数,因为Boy类只知道有Girl类,但是是不知道Girl类里有这个KISS函数的,因为我们的Girl 的kiss函数是在Boy类的后面。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-3-25 14:57:14 | 显示全部楼层
muyu0096 发表于 2016-3-24 16:53
恩,从你的原意来看,这是实现不了,至少我的水平实现不了
不过,这也不正说明了你的题目么。。。搞基和 ...

我成功的阻止了 搞基和拉拉  哈哈哈
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-3-26 17:30:00 | 显示全部楼层
奥古斯丁少爷 发表于 2016-3-25 14:57
我成功的阻止了 搞基和拉拉  哈哈哈

贴代码看看
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-26 22:48

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表