C++笔记_03面向对象3

20160803.cpp :  定义控制台应用程序的入口点

01:41:37
#include "stdafx.h"
//#include<iostream>
//
//using namespace std;
//
///*
//构造函数的初始化列表
//*/
//
///*
//面向过程  程序 = 数据 + 算法
//
//
//面向对象  程序 = 对象 + 对象 + 。。。 +消息
在一个程序里对象所属的类是不允许单独存在的,
//
//组合(聚合) a part of...  谁是谁的一部分(谁需要借用谁的功能)
// :: 我这类的对象,变成了另一个类的成员对象
//
//继承 a kind of...  谁是谁的一种(一个分类)
//
//
//
//
//指向成员的指针
//
模拟用户登录的系统模块
//
//
//*/
//
//
用链表存储用户名和密码(带有头结点的链表)
//class CLink
//{
//public:
// CLink();
// ~CLink();
// void insert(char *n,char *p);
//
//private:
// struct Node
// {
// char _name[20];
// char _pwd[20];
// Node *_pnext;
// };
//};
//
//
//
数据存储模块,,数据结构存储用户名和密码
//class CUserDB
//{
//public:
// bool query(char *n,char *p);//返回登录成功与否
// bool Register(char *n,char *p);//注册
//private:
// CLink _linkDB;
//};
//
//
//
菜单栏
//class CMenu
//{
//public:
// CMenu();
// void Run();
// void ShowLoginMenu();//1. login登录 2.register 注册 3.exit退出
//private:
// char name[20];
// char pwd[20];
// bool _bRunnong;
// CUserDB _userDB;
//
//};
//
//int main()
//{
// CMenu menu;
// menu.Run();
//
// return 0;
//}
//
//
//#if 0
指向成员的指针
///*
//函数指针调用函数 与 函数名调用函数 的区别
//*相同点:  两个都表示函数代码段的起始地址,调用函数的栈帧的开辟与回退是一样的
//*不同点:   1. 函数指针调用函数的时候,不会处理内联函数
// 因为内联函数是在编译阶段处理的,指针调用是在链接阶段
// 2.、如果使用函数名调用,则多次调用不同函数时,需要重复使用不同函数名去调用
//  、如果使用函数指针,则无论是普通调用还是形参,只需要参数类型与返回值一致即可,
//  不用重复使用函数名,就可以重复调用
// 3.函数指针必须指向一个已经初始化的函数
//
// <施老师说>  用函数指针没有用函数名调用效率高
// 函数指针并不好,写着麻烦,不易理解,
//
//*/
//class Test
//{
//public:
// //C++调用约定是 _thiscall
// Test(int data):ma(data){}
// void show()
// {
// cout<<"Test::show ma:"<<ma<<endl;
// }
// int ma;
//};
//
C语言调用约定是 _cdecl   
//void show()
//{
// cout<<"call ::show"<<endl;
//}
//
//int main()
//{
// Test t1(20);
// t1.show();
// cout<<t1.ma<<endl;
//
// //函数指针赋值
// void (*pfunc1)()=show;//该指针不能指向调用约定不同的函数
// pfunc1();//调用
//
// void (Test::*pfunc2)() = &Test::show;//对象成员方法指针初始化赋值
// (t1.*pfunc2)();//函数指针调用成员方法1
//
// Test *p = new Test(20);
// (p->*pfunc2)();//函数指针调用成员方法2
// delete p;
//
// int data = 10;
// int Test::*p2=&Test::ma; //一个指针不能直接指向一个成员方法,需要说明作用域
// t1.*p2 = 20;
// p->*p2 = 30;
//
// return 0;
//}
//#endif
//
//#if 0
//class Test
//{
//public:
// //只要是构造函数,都支持函数的初始化列表的
// //成员变量的初始化方式和它们定义的先后顺序有关,
// //跟初始化列表里的先后顺序无关
// //
// //
// Test(int data=100):mb(data),ma(data)
// {
// /*mb = data;
// ma = mb;*/
// }
//
// void show()
// {
// cout<<"ma:"<<ma<<" mb:"<<mb<<endl;
// //ma 无效值-858993460  mb 100
// //&ma 9195584    mb 100
// }
//
// void operator=(const Test &src)
// {
// ma = src.ma;//这里和默认的赋值重载函数不一样,这里是this->ma 被赋值 成了 src.ma,两个ma占用不同的内存
// mb = src.mb;
// }
//
//private:
// int &ma;
// int mb;
//};
//
//int main()
//{
// Test t;
// t.show();
//
// Test t1(t);//调用拷贝构造函数,没有写拷贝构造函数,就调用默认的拷贝构造函数
// t1.show();
//
// /*
// 在成员变量里出现引用变量的时候,
// 编译器无法产生一个默认的赋值运算符重载函数
// 因为引用变量一但初始化,就不能再改变了
// */
// t1 = t;//编译通不过,
//
//
//
// return 0;
//}
//#endif
//
//
//
//#if 0
//class Date
//{
//public:
// Date(int y=0,int m=0,int d=0)
// {
// _year = y;
// _month = m;
// _day = d;
//
// }
//
// void show()
// {
// cout<<_year<<"/"<<_month<<"/"<<_day<<endl;
// }
//
//private:
// int _year;
// int _month;
// int _day;
//
//};
//
//
//
//class CStud
//{
//public:
// //构造函数的初始化列表 -》 指定成员变量的初始化方式
// //1.int _age = a; 2.int _age; 3._age = a;
// //对于内置类型以上没有区别
// //但是对于类对象1.调用相应的构造函数
// //  2.先调用默认构造
// //  3.先产生临时对象,再赋值,再析构临时对象
//
// CStud(char *n,int a,float s,int y,int m,int d)
// :_age(a)
// ,_score(s)
// ,_date(y,m,d)    //Date _date(10,10,10);   /*  冒号后面是初始化列表*/
// {
// //成员对象都已经构造完成了
// //(这里进入之前需要完成所有成员对象的构造)
// strcpy(_name,n);
// //_age = a;
// //_score = s;
// }
//
// void show()
// {
// cout<<"name: "<<_name<<endl;
// cout<<"age: "<<_age<<endl;
// cout<<"score: "<<_score<<endl;
// _date.show();
// }
//
//private:
// char _name[20];
// int _age;
// float _score;
// Date _date;//成员对象(日期)
// //QUESTION1:: 成员对象该怎么初始化?
// //1.在此处不能给成员对象初始化,因为在C++中,编译器对类中的初始数据变量是不分配内存的,只是对实体对象的抽象说明而已
//
//};
//
//int main()
//{
// /*
// 对象的构成的步骤
// 1根据对象的类型 给对象 分配内存
// 2构造 当前对象的成员对象
// 3根据对象定义的方式 调用 相应的构造函数
// */
//
// CStud stud1("name1",26,98.5,1990,1,1);
// stud1.show();
//}
//
//
//
//
///*
//复习:对象的生存周期
//*/
//
//class Test
//{
//public:
// Test(int a=0)
// {
// cout<<"Test(int)"<<endl;
// ma = a;
// }
//
// Test(const Test &src)
// {
// cout<<"Test(const Test&)"<<endl;
// ma = src.ma;
// }
// void operator=(const Test &src)
// {
// cout<<"Test::operator="<<endl;
// ma = src.ma;
// }
//
//
// ~Test()
// {
// cout<<"~Test()"<<endl;
// }
//
// int GetValue(){return ma;};
//private:
// int ma;
//};
//
///*
//Test GetObject(Test);
//实参和形参的类型,个数是否匹配
//函数调用点返回值的类型和声明或定义返回值的类型是否匹配
//根据返回值的类型确定返回方式
//
//mov dword ptr[ebp-8],eax   x86平台是通过eax带出来函数的返回值的
//*/
//Test GetObject(Test &t)
//{
// int value = t.GetValue();
// //Test tmp(value);  //这个会产生构造
// //return tmp;  //返回一个已经存在的对象,这样会产生拷贝构造
// return Test(value);//返回对象的时候,直接返回对象,这样满足编译器优化规则,
// //这样直接构造临时对象,将临时对象值返回,然后析构临时对象
//
//}
//
//
//void test1(Test *p)
//{
// int a=10;
// cout<<"call test1"<<endl;
//}
//
//Test * test2()
//{
// //test t(30);
// return &Test(30);
//}
//
debug版本中inline不起作用
//
//int main()
//{
// //test1(&Test(20));//显示产生的临时对象,不能用指针指向,遇到分号,? ,都会析构,指针会变成野指针
// // //此处是可以的,但是预防习惯,其他情况下不可以,,所以尽量不要这样写
// //Test *p = test2();
//
// Test t1(10);
// //Test t2;//需要默认的构造函数(有缺省值),否则构造不出来
//
// //t2 = GetObject(t1);//函数调用 堆栈开辟过程  mov dword ptr[ebp-8],eax
// //ebp+8临时量地址
// //ebp 栈底指针    esp栈顶指针
// //回退通过eax寄存器带出值
// //1.如果是:Test tmp(value);  //这个会产生构造
//  //return tmp;  //返回对象,这样会产生拷贝构造
// //2.如果是:return Test(value);//返回对象的时候,直接返回对象,这样满足编译器优化规则,
// //这样直接构造临时对象,将临时对象值返回,然后析构临时对象
// //综上::建议使用第二种
//
// Test t2 = GetObject(t1);//应该定义的时候直接赋值,,也就是初始化,这样效率贼高
//
//
//
//
// cout<<t2.GetValue()<<endl;
//
//
//
//
//
//
// return 0;
//}
//#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值