您的位置:首页 > 编程语言 > C语言/C++

VS2010 C++ MFC框架学习笔记4 - C++面向对象编程基础2

2015-06-09 16:30 821 查看
跟着教材《Visual C++ 2010 MFC 编程入门》.pdf 学习了2周,感觉有些基础的概念不太清楚,所以找出网易学堂的VC++课程进行学习http://tech.163.com/special/0009159F/vc.html

===========================================

[第二课 C++经典语法与应用 类的编写与应用]
===========================================

构造函数:采用类的方式来保证它的唯一性,取个类名,没有返回值,对类里的变量进行初始化。

析构函数:回收内存,没有返回,没有参数。

例:

#include<iostream>
using namespace std;
class Point{
public:
	int x;
	int y;
	Point(){	//构造函数,同,类名
		x = 0;
		y = 0;
	}

	Point(int a, int b){ //构造函数,带参
		x = a; y = b;
	}

	~Point(){	//析构函数,取反符号+类名
	}

	void output(){
		cout<<x<<endl<<y<<endl;
	}
	void output(int x, int y){
		this->x = x;	//this point, 指向对象
		this->y = y;
	}
};

void main(){
	Point pt(3,3);
	pt.output(5,5);
	pt.output();
}


上例中,出现了两个Point()构造函数,这种情况称为函数的重载:函数重载是指在同一作用域内,可以有一组具有相同函数名,不同参数列表的函数,这组函数被称为重载函数。重载函数通常用来命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。参考:http://www.cnblogs.com/skynet/archive/2010/09/05/1818636.html

this指针是一个隐含的,指向对象本身,代表对象地址的指针;一个类所有的对象调用的成员函数都是同一代码段,如何区分不同对象但是同一类下的成员函数的执行呢?其实,成员函数除了接受参数外,还接受了一个对象的地址,这个地址被一个隐含的形参this指针所获取,等同于执行 this = &pt. 所有对数据成员的访问都隐含地被加上前缀this->

继承:

====================public; protected; private在继承中,对method的保护权限区别: 》public 是外部Y访问,子类Y访问 》protected 是外部N访问,子类Y访问 》private 是外部N访问,子类N访问如:

#include<iostream>
using namespace std;

class Animal{
public:
    void eat(){
        cout<<"animal eat"<<endl;
    }
protected:
    void sleep(){
        cout<<"animal sleep"<<endl;
    }
private:
    void breathe(){
        cout<<"animal breathe"<<endl;
    }
};

class Fish : public Animal{ //子类的继承特性:这里是public式继承
    void test(){
        sleep(); //protected,子类中可以访问
        //breathe();//private,子类都不能access
    }
};

void main(){    
    Animal an;
    an.eat();
    Fish fh;
    //fh.sleep();//protected, cannot access
}


这里有个继承的权限叠加后,对method的最终对外访问权限的判定问题:

基类method的权限: 子类的继承特性: 最终对外访问特性:

基类method权限类继承特性子类的访问特性
Public

Protected

Private
PublicPublic

Protected

No Access
Public

Protected

Private
ProtectedProtected

Protected

No Access
Public

Protected

Private
PrivatePrivate

Private

No Access
------------------

构造函数的访问顺序

父类{

父类的构造函数(){

指令1;

}

~父类的构造函数(){

指令2;

}



}

子类:public 父类{ //继承

子类的构造函数(){

指令3;

}

~子类的构造函数(){

指令4;

}

}

main(){

子类.子类obj;

}

====执行结果:====

指令1;

指令3;

指令4;

指令2;

--------

如果父类的构造函数带参数,而子类不带,则子构造函数:

Fish():Animal(400,300){

}

========================



完整代码:

#include<iostream>
using namespace std;

class Animal{
public:
	Animal(int x, int y){
		cout << "animal construct"<<endl;
		cout << x <<endl;
		cout << y <<endl;
	}

	void eat(){
		cout<<"animal eat"<<endl;
	}
protected:
	void sleep(){
		cout<<"animal sleep"<<endl;
	}
private:
	void breathe(){
		cout<<"animal breathe"<<endl;
	}
};

class Fish : public Animal{
public:
	Fish():Animal(300,400),a(11){ 
		cout<<"fish construct"<<endl;
		cout<<a<<endl;
	}

	void test(){
		sleep(); //protected,子类中可以访问
		//breathe();//private,子类都不能access
	}
private:
	const int a;
};

void main(){	
	//Animal an;
	//an.eat();
	Fish fh;
	//fh.sleep();//protected, cannot access

	getchar();
}


函数的覆盖:

发生在父类和子类之间的,父类下有个method_name(){},子类下也有个同名method_name(){},则子类的obj优先执行子类的函数/method

但是,如果又要用父类的method,则使用两个冒号来作为作用域标识符,例:

class Fish : public Animal{
public:
	Fish(){
	}
	void breathe(){
		Animal::breathe(); //此处就是调父类的breathe()来
		cout<<"fish bubble"<<endl;
	}
};


C++继承的多态性:

void fn(Animal *pAn){  //有一个全局函数,输入Animal指针,找指针下的breathe()方法进行执行。
    pAn->breathe();
}

void main(){
    Fish fh;    //obj Declare
    Animal *pAn;    //pointer Declare
    pAn = &fh;    //赋值
    fh(pAn);    //调用
}
//因为Fish是Animal的子类,
//目测会调用Fish的breathe()函数来执行,
//但是却执行了Animal类下的breathe()
原因就是Fish和Animal是共用的一个内存起始地址。如下:

—————

| Animal |

—————

| Fish |

—————

如果要根据不同的类型(Animal or Fish)来调用不同类(Animal or Fish)下的函数,则可利用C++的多态性,在Animal的breathe()前加个virtual,将之定义为“虚函数”,让C++编译器作一个 late binding迟绑定。就可以了:

virtual void breathe(){
        cout<<"Animal breathe"<<endl;
    }

此时,再运行 fn(pAn) ,如果子类中有 breathe,则就会调用子类Fish中的breathe,如果没有,再调用Animal中的breathe

纯虚函数:

让父类只有操作名称,而没有具体的操作内容;让派生类在继承时候再具体地给出它的定义。

Animal 下:  virtual void breathe() = 0;

Fish 下:    void breathe(){ cout <<"fish bubble..."<<endl ;}

在不确定这种行为具体表现形式,而这种行为又是必须的,就可以在基类中以这种纯虚函数来。

C++中的引用:

把工程文件按.h & .cpp来管理:

.h 文件用于类的声明;

.cpp文件用于类的定义。

这里,Fish是继承于Animal的类,则include""的顺序要注意:


一个进一步的模型是:


也就是说,在main.cpp中include了Animal.h & Fish.h; 在Fish.h & Animal.cpp中,include"Animal.h" ; 在Fish.cpp中 include“Fish.h”

这里会有一个错误:因为main.cpp引用了Animal.h,同时main.cpp引用了Fish.h,而Fish.h再次引用了Animal.h,所以会报Animal.h中的类被重复定义。怎么办呢?使用预编译命令: #ifndef #def #endif

使用预编译命令

main.cpp引用了Animal.h,然后main.cpp引用了Fish.h,而Fish.h再次引用了Animal.h,所以会报Animal.h中的类被重复定义。怎么办呢?

使用预编译命令: #ifndef #def #endif

//File: Animal.h
//Declare the Animal class and the functions
//
#ifndef ANIMAL_H_H //用预编译指令符防止类的重复编译错误: if not define
#define ANIMAL_H_H //用预编译指令符防止类的重复编译错误: define
class Animal{
public:
	Animal(int height, int weight);//构造函数
	void eat();//
	void sleep();//
	virtual void breathe();//virtual
};
#endif  //用预编译指令符防止类的重复编译错误: end if


VC++编译链接过程

先对cpp文件进行编译,编程成obj文件,h头文件不参与编译。最后进行链接。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: