资源描述
/*****************************************************************/
一、面向对象编程
1 什么是对象
万物皆对象
世界是由一组相互之间紧密联系的对象组成的。
通过将对象按照属性、行为共性进行分类,达到将具体事物进行抽象的结果
通过程序的语法表达对象属性和行为的抽象--面向对象
将面向对象的思想用于编程的过程--面向对象(OOP)
2 为什么面向对象?
面向对象的编程思想适合于大型的软件的开发
面向对象的方法能够有效的提高软件的开发效率
借助强大的逻辑建模能力将问题域和方法域有机的统一起来
软件工业的发展趋势
3 怎么面向对象?
熟练的掌握至少一种面向对象的语言
精通至少一种面向对象的元语言,如:UML
深入学习设计模式和面向对象的设计方法 GOF
二、类
学生
属性:姓名、年龄
行为:学习
类就是通过对属性和行为的抽象,描述一组对象的语法结构
1 类的定义
class class_name{
..
};
eg.
class Student{
..
}
2 通过成员变量来表的类的属性
class class_name{
类型 成员变量名
}
class Student{
string m_name;
int m_age;
};
3 通过成员函数来表达行为
class class_name{
返回类型 成员函数名(形参表){
函数提;
}
}
eg.
class Student{
string m_name;
int age;
void learn(const string & lesson){
}
};
将成员函数和定义分开
class Student{
string m_name;
int age;
};
void Student::learn(const string & lesson){
};
4:通过访控属性约束属性和行为的访问方式
访控属性
缺省的访控属性为私有private //结构体与类的唯一区别
公有成员:public 谁都可以访问
私有成员:private 只有自己可以访问
保护成员:protected 只有自己和自己的子类可以访问
class Student{
private:
string m_name;
int age;
public:
void learn(const string & lesson){
}
};
5 构造函数
class class_name{
类名(形参表):初始化表{
函数体
}
};
该类的对象创建时,相应的构造函数被自动执行.创建对象的同时提供构造实参的表,与构造函数的形参匹配
栈:开辟空间===》调用构造函数初始化
堆:new -> 条用构造函数
string类会调用缺省构造初始化为空
<1>构造函数可以重载
<2>缺省构造函数
如果一个类中没有定义任何构造函数,那么系统会自动为其提供一个无参的构造函数。缺省构造函数对于基本类型的成员不做初始化,而对类类型的成员变量,通过相应类型的无参构造函数做初始化
<3>几个特殊用途的构造函数:默认初始化
A 无参构造函数
Student :: Student(void){}
或
?? Studebt :: Student(const string & name = "",int age = 0){}
B 类型转换构造函数:自定义的类型转换
A::A(const B & b){}
A::A(B b){}
B b;
A a = b;
A a(b);
void foo(A,a)
foo(b)
A foo(void){
B b,
return b;
}
通过explicit关键字可以指明通过构造函数所完成的类型转换必须显示的进行
C 拷贝构造函数:同类型对象的克隆
A::A(const A & that){}
如果类中没定义拷贝函数系统会自动提供一个缺省的拷贝构造函数,该函数对于基本类型的成员变量,按字节复制,对于类类型的成员变量,调用相应的拷贝函数,完成复制。在大多数情况下,缺省拷贝函数是主够用的,不需要自定义拷贝函。
class A{}//无参(缺省)、拷贝(缺省)
class A{
public: //无参(自)、拷贝(缺)
A(void){
}
}
class A{
A(int a){ //自(),拷贝(缺)
}
}
class A{
A(const A & a){ //就这一个
}
}
<4> 初始化表
初始化只和声明顺序有关
A 语法
使得成员变量的初值在调用构造函数的压栈时就赋值而不是在构造函数中
类名::类名(构造形惨表):成员变量(初始值),....
class Student{
public:
/*
Student(const string & name,const int age){
m_name = name;
m_age = age;
}
*/
Student(const string & name,const int age):m_name(name),m_age(age){
}
/* Student(void){
m_name = "匿名";
m_age = 0;
}
*/
Student(void):m_name("匿名"),m_age(0){
}
private:
string m_name;
int m_age;
};
B 必须使用初始化的场合
含有类类型的变量,而变量的类型没有无参构造函数
含有常量或引用型成员变量
const int a;
a = 10
int & r;
r = b;
??C 拥有一个不带无参构造的基类.
D 成员变量的初始顺序仅与其在类中被声明的顺序有关,而与其在初始化列表中顺序无关
class X{
public:
X(string str):m_str(str),m_len(m_str.length()){}
int m_len;
string m_str;
};
6 把类的声明和实现分开
实际开发中通常将类的声明部分放到.h中,实现放在.cpp中
7 在C++中类和结构体没有本质的区别,唯一不同的是类的缺省访控属性为私有,而结构体为共有
练习:实现一个CLock类,在构造函数中将Clock初始化为当前系统时间,通过成员函数在屏幕上显示电子钟
16:09:26
三、this指针
1 一般而言,关键字this 是一个指针,在普通成员函数中this指针指向调用该函数的对象,在构造函数中this指向这个正在正在被构造的对象
2 应用场景
<1> 在成员函数/构造函数中明确表示所引用的变量是一个成员变量,以避免和同名的参数变量,及局部变量发生冲突
/***************************************************************/
#include <iostream>
using namespace std;
//#define __class__
#ifdef __class__
class Student{
public:
/*
Student(const string & name,const int age){
m_name = name;
m_age = age;
}
*/
Student(const string & name,const int age):m_name(name),m_age(age){
}
/* Student(void){
m_name = "匿名";
m_age = 0;
}
*/
Student(void):m_name("匿名"),m_age(0){
}
void learn(const string & lesson){
cout << m_age << " 岁的 " << m_name << "同学 在学" << lesson <<endl;
}
/*//编译器对上面的函数做了如下修改
void learn(Student * this,const string & lesson){
cout << this->m_age << " 岁的 " << this->m_name << "同学 在学" << lesson <<endl;
}
*/
void setName(const string & name){
if(name == "2"){
cout << "你才2" << endl;
}else{
m_name = name;
}
}
void setAge(const int age){
if(age < 0){
cout << "invalid age < 0" <<endl;
}else{
m_age =age;
}
}
private:
string m_name;
int m_age;
};
int main(void){
/*
Student student;
student.setName("2");
student.setAge(9);
student.setName("刘德华");
student.setAge(9);
student.learn("C++");
*/
Student student("刘德华",18);
student.learn("C++");
/*
learn(&Student,"C++");
*/
Student * ps = new Student("毛泽东",8);
ps->learn("C");
/*
learn(ps,"C");
*/
delete ps;
Student * ps1 = new Student();
ps1->learn("UNIX C");
delete ps1;
Student student2;//Student student2();是不对的
student2.learn("法轮大法");
return 0 ;
}
#endif
//define __cast__
#ifdef __cast__
class Integer{
public:
explicit Integer(int value){ //explicit 必须显示的转换
m_value = value;
}
void print(){
cout << m_value << endl;
}
Integer operator + (const Integer & i){
cout << m_value + i.m_value << endl;
}
int m_value;
};
int main(void){
?? Integer i = static_cast<Integer>(100);
//其他转换风格也可以(Integer)100/Integer(100)
i.print();
(i + Integer(400));
return 0;
}
#endif
//#define __copy__
#ifdef __copy__
class Dog{
public:
Dog(const string & name){
m_name = name;
}
/*
Dog(const Dog & that){
//Dog(const Dog that){//无限递归了
m_name = that.m_name;
}
*/
void talk(void){
cout << m_name << " WangWang!" <<endl;
}
private:
string m_name;
};
//void foo(Dog dog){
void foo(Dog& dog){
dog.talk();
}
int main(void){
Dog dog1("You");
dog1.talk();
Dog dog2(dog1);
dog2.talk();
foo(dog1);
return 0;
}
#endif
//#define __inint_list__
#ifdef __inint_list__
class Integer{
public:
//Integer(void){}
Integer(int value):m_value(value){}
int m_value;
};
class Student{
public:
Integer m_age;
//Student(int age){
Student(int age):m_age(age){
m_age = Integer(age);
}
};
class Dumy{
public:
Dumy(int c,int & r):m_c(c),m_r(r){
}
const int m_c;
int & m_r;
};
int main(void){
Student stu(23);
int a = 1000;
Dumy dumy(100,a);
cout << dumy.m_c << ' ' << dumy.m_r << endl;
return 0;
}
#endif
#define __this__
#ifdef __this__
class A{
public:
A(void){
cout << "craet fun" << this << endl;
}
void foo(void){
cout << "craet fun" << this << endl;
}
A(int i){
//i = i;
this -> i = i;
}
//A(int i):i(i){}//可以的
int i;
};
int main(void){
A a;
cout << &a << endl;
a.foo();
return 0;
}
#endif
展开阅读全文