掌握C++[初学]
刚刚开始学c++,共勉。
- C++的标准输入输出流
- C++的特性
- 类的继承访问特性
C++的标准输入输出流
C++中提供了一套自己的输入、输出方式,它们是cin 、cout和cerr,相当于c中的三个文件指针stdin、stdout、stderr,分别指向终端输入、终端输出和标准出错输出(也从终端输出)。
cin和cout比C语言中的scanf和printf有一个巨大优势,cin和cout可以自动判别输入输出数据类型而自动调整输入输出格式,不必像scanf和printf那样一个个由用户指定。
cin与>>一起完成输入操作,cout、cerr与<<一起完成输出与标准错误输出。
举例 | c语言 | c++ |
---|---|---|
输入x | int x; | cin>>x; |
输出x | printf( ); | cout<<; |
换行 | /n | endl |
代码举例1
#include <iostream.h>
struct point1 //结构体定义,没有像class的访问定义,属于
//缺省状态,类似class里的privarte声明
//class point1 //类定义
{
/**********************
public: //所有的成员可外部访问
privarte: //只能在该单个类内部访问,相互类之间、外部都不
//能访问,struct(结构体)定义的都属于
//privarte声明,不能外部访问
pretected: //子类父类之间访问,但是子、父类之外也不能访问
以上三个类型属于类(class)的配套使用规则,在进行x,y输入前对本类的性质提前进行定义(是否可被访问)。
**********************/
int x;
int y;
void output()
{
//c++可以在类里边继续进行定义,在c不能进行output的定义
cout<<x<<endl<<y<<endl;
}
};
void main()
{
point1 pt;
pt.x=5;
pt.y=5;
//cout<<pt.x<<endl<<pt.y<<endl;
pt.output();
}
C++的特性
代码举例2
#include <iostream.h>
class point1 //类定义
{
public:
int x;
int y;
void init()
{
x=0;
y=0;
}
void output()
{
cout<<x<<endl<<y<<endl;
}
};
void main()
{
point1 pt; //pt无值
pt.init();
pt.output();
}
//输出结果:0 0 相当于初始化 x,y
代码举例3 构造函数
#include <iostream.h>
class point1 //类定义
{
public:
int x;
int y;
/*void init()
{
x=0;
y=0;
} */
point1 pt() //构造函数,唯一
{
x=0;
y=0;
}
void output()
{
cout<<x<<endl<<y<<endl;
}
};
void main()
{
point1 pt; //调用pt,内部已经有值
//pt.init();
pt.output();
}
//输出结果:0 0 相当于初始化 x,y
构造函数
1、构造函数最重要的作用是创建对象本身 (刚刚是初始化)。
2、C++规定,每个类必须有一个构造函数,没有构造函数,就不能创建任何对象。
3、C++又规定,如果一个类没有提供任何的构造函数,则C++提供一个默认的构造函数(由C++编译器提供),这个默认的构造函数是一个不带参数的构造函数,它只负责创建对象,而不做任何的初始化工作。
4、只要一个类定义了一个构造函数,不管这个构造函数是否是带参数的构造函数,C++就不再提供默认的构造函数。也就是说,如果为一个类定义了一个带参数的构造函数,还想要无参数的构造函数,则必须自己定义。
代码举例4 析构函数
#include <iostream.h>
class point1 //类定义
{
public:
int x;
int y;
point1 pt() //构造函数,唯一
{
x=0;
y=0;
}
~point1() //析构函数,回收内存
{
}
void output()
{
cout<<x<<endl<<y<<endl;
}
};
void main()
{
point1 pt; //调用pt,内部已经有值
//pt.init();
pt.output();
}
析构函数
1、当一个对象生命周期结束时,其所占有的内存空间就要被回收,这个工作就由析构函数来完成。
2、析构函数是“反向”的构造函数,析构函数不允许有返回值,更重要的是析构函数不允许带参数,并且一个类中只能有一个析构函数。
3、析构函数的作用正好与构造函数相反,对象超出其作用范围,对应的内存空间被系统收回或被程序用delete删除时,析构函数被调用。
4、根据析构函数的这种特点,我们可以在构造函数中初始化对象的某些成员变量,给其分配内存空间(堆内存),在析构函数中释放对象运行期间所申请的资源。
代码举例5 重载
#include <iostream.h>
class point1 //类定义
{
public:
int x;
int y;
point1() //构造函数,唯一
{
x=0;
y=0;
}
point1(int a,int b) //构造函数,唯一
{
x=a;
y=b;
}
~point1() //析构函数,回收内存
{
}
void output()
{
cout<<x<<endl<<y<<endl;
}
};
void main()
{
point1 pt(3,3); //调用pt,内部已经有值
//pt.init();
pt.output();
}
//名字一样的函数名,但是函数参数不一样
函数的重载
重载构成的条件:函数的参数类型、参数个数不同,才能构成函数的重载。
以下两种情况,均不能构成函数的重载。
第一种情况: (1)void output();(2)int output();
第二种情况:(1)void output(int a,int b=5);
(2)void output(int a);
代码举例6 this指针
#include <iostream.h>
class point1 //类定义
{
public:
int x;
int y;
point1() //构造函数,唯一
{
x=0;
y=0;
}
point1(int a,int b) //构造函数,唯一
{
x=a;
y=b;
}
~point1() //析构函数,回收内存
{
}
void output()
{
cout<<x<<endl<<y<<endl;
}
void output(int x,int y)
{
x=x;
this->y=y;
}
};
void main()
{
point1 pt(3,3); //调用pt,内部已经有值
pt.output(5,5);
//pt.init();
pt.output();
}
//输出值为3 5,x=x相当于没有实际定义
this指针
1、this指针是一个隐含的指针,它是指向对象本身,代表了对象的地址 ;
2、一个类所有的对象(例如,x,y)调用的成员函数都是同一代码段。那么成员函数又是怎么识别属于同一对象(x,y)的数据成员呢?
原来,在对象调用point1 pt(3,3)和pt.output(5,5)时,成员函数除了接受2个实参外,还接受到了对象x和y的地址。pt地址被一个隐含的形参this指针所获取,它等同于执行this=&pt。所有对数据成员的访问都隐含地被加上前缀this->。
提示:在以后的MFC编程中,如果在成员函数中想调用同类中的某个成员,可以使用VC++提供的自动列出成员函数功能,使用this->,VC++将列出该类中的所有成员,我们可以从列表中选择我们想调用的成员。
类的继承访问特性
代码举例7 类的继承
#include <iostream.h>
class Animal
{
public:
void eat()
{
cout<<"animal eat"<<endl;
}
void sleep()
{
cout<<"animal sleep"<<endl;
}
void breathe()
{
cout<<"animal breathe"<<endl;
}
};
class Fish : public Animal //继承,Animal父类,Fish子类
{
};
void main()
{
Animal an;
an.eat();
Fish fh;
fh.sleep();
}
<在C++中,给我们提供了一种重要的机制,就是继承。 理解继承是理解面向对象程序设计的关键。
代码举例8 继承特性
#include <iostream.h>
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 //继承,Animal父类,Fish子类
{
void test() //子类可以访问protected
{
sleep();
// breathe(); 子类不可以访问 private
}
};
void main()
{
Animal an;
an.eat();
Fish fh;
// fh.sleep(); 外部不能访问protected,报错
}
基类的访问特性 | 类的继承特性 | 子类的访问特性 |
---|---|---|
Public; Protected; Private | Public | Public; Protected; No access |
Public; Protected; Private | Protected | Protected; Protected; No access |
Public; Protected; Private | Private | Private; Private; No access |
代码举例9 继承+构造+析构
include <iostream.h>
class Animal
{
public:
Animal(int height,int weight)//带参数构造函数
{
cout<<"animal construct"<<endl;
}
~Animal()
{
cout<<"animal deconstruct"<<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 //继承,Animal父类,Fish子类
{
public:
Fish():Animal(100,150)//继承带参数的构造函数
{
cout<<"fish construct"<<endl;
}
~Fish()
{
cout<<"fish deconstruct"<<endl;
}
void test() //子类可以访问protected
{
sleep();
// breathe(); 子类不可以访问 private
}
};
void main()
{
//Animal an;
//an.eat();
Fish fh;
// fh.sleep(); 外部不能访问protected,报错
}
//输出结果:构造函数先父后子,析构函数先子后父
animal construct
fish construct
fish deconstruct
animal deconstruct
代码举例10 函数覆盖
#include <iostream.h>
class Animal
{
public:
Animal(int height,int weight)
{
//cout<<"animal construct"<<endl;
}
~Animal()
{
//cout<<"animal deconstruct"<<endl;
}
void eat()
{
cout<<"animal eat"<<endl;
}
void sleep()
{
cout<<"animal sleep"<<endl;
}
void breathe()
{
cout<<"animal breathe"<<endl;
}
};
class Fish : public Animal //继承,Animal父类,Fish子类
{
public:
Fish():Animal(100,150),a(1)
{
//cout<<"fish construct"<<endl;
}
~Fish()
{
//cout<<"fish deconstruct"<<endl;
}
void breathe()
{
Animal::breathe(); //::作用域标识符,两种并存
cout<<"fish bubble"<<endl; //函数覆盖
}
private:
const int a;
};
void main()
{
Fish fh;
fh.breathe();
}
无Animal::breathe();
输出结果:fish bubble,函数覆盖;
有Animal::breathe();
输出结果:animal breathe
fish bubble
函数的覆盖
函数的覆盖是发生在父类与子类之间的。