相较于我之前学到的c++(c+STL)二级考的才是真的c++,我不想浑浑噩噩过去只想真正的学会,串联起来c和c++的基础语法只是:面向对象编程:
在我看来类就是把c松散的函数以及定义打包封装了起来,使得程序看起来更加美妙
调用对象时,系统自动调用默认函数,如果有与之对应的构造函数,系统调用构造函数,构造函数就是创建对象时调用的函数,构造函数在创建对象时就要调用,用于对对象属性的初始化,所有的对象创建时都需要初始化才能完成,如果没有构造函数就会默认一个空参数的构造函数,如果定义的构造函数这个默认空参数的构造函数就不复存在了
- 构造函数的特点:
- (1): 构造函数的名称与所在类的名称相同
- (2): 构造函数不需要定义返回值的类型
- (3): 构造函数没有具体的返回值
- (4): 一般配有一个~开头的析构函数
- 例子
class myclass
{
public:
//myclass(){}默认构造函数
myclass(int len)
{
array=new int[len];
arraysize=len;
......
}
~myclass()
{ delete [] array; }
void print()
{
......
}
private:
int *array;//new出新数组的首地址
int arraysize;
}
就是在已有类的基础之上创建新的类,已有的类称为基类(父类),新的类称为派生类(子类),换句话说就是将基类中的某个数据拿给基类来用,同一个基类可以被多个派生类继承,同一个派生类同样也可以继承多个基类,从一个基类继承叫做单继承,否则叫做多继承
- (1): 派生类除了可以使用继承类的某些数据或者成员也可以新增自己的数据及成员
- (2): 派生类可以改变基类在派生类里面的属性
- (3): 派生类不能继承基类的构造析构以及友元函数
- (4): 派生类不可以继承静态数据成员和静态成员函数
- 访问权限问题:
访问位置 | 类内部 | 子类 | 类的对象 |
---|---|---|---|
变量公开度 | |||
private | 可以 | 不可以 | 不可以 |
protected | 可以 | 可以 | 不可以 |
public | 可以 | 可以 | 可以 |
private需要的访问权限最高:即只有内部成员可以访问,但可以通过父类的共有变量来间接访问
protected需要的访问权限中等:内部成员可以访问,也可以被子类
派生类的继承方式是子类中的最低权限,要是共有继承public依旧是public,protected依旧是protected,但是要是保护继承public也在子类中变成protected,私有继承类似,继承过来的在子类中全部变为私有
#include<iostream>
#include<string>
using namespace std;
class father
{
public:
father(){size=5;}
void printff()
{
cout<<size<<endl;
}
//1.public://2.protected//3.private
int size;
};
class son:/*4.public//5.protected//6.private*/ father
{
public:
son():father(){}
void printss()
{
cout<<size<<endl;
}
};
int main()
{
father f;
cout<<f.size<<endl;
f.printff();
son s;
cout<<s.size<<endl;
s.printff();
s.printss();
return 0;
}
1+4:5 5 5 5 5
1+5:5 5 _ _ 5
//经转成protected不可以被自己对象访问
1+6:5 5 _ _ 5
//经转成private不可以被自己对象访问,不加转换默认private
2+4:_ 5 _ 5 5
//相当于根据权限依次写入,所以f.size和s.size不可以被访问
2+5:_ 5 _ _ 5
//printff转化为子类的保护变量不能被对象访问
2+6:_ 5 _ _ 5
......
根据转化关系判断就好
- 继承中的构造函数问题:
- 子类的构造函数必须调用父类的构造函数
- 先调用父类后调用子类的构造函数
Son(string name,int age):Father(name,age){}
虚函数就是在基类中被关键字virtual说明,并在派生类中重新定义的函数,虚函数的作用是允许在派生类中重新定义与基类中重名的函数
*表示单一就代表定义指针变量或者说定义指针函数返回值是指针,取值时应用->
&即代表取址又代表引用一般来说引用比较好辨别int &a=b就是引用的类型,其余是取址,引用可以改变实参而且提速程序,运用广泛没有引用函数,对象取值是 .
- 为什么要重载运算符呢,这是因为类与类之间不能进行我们想要的运算,但是在类的内部重载运算符后就能实现我们想要的运算符操作
int a=10,b=10;
int c=a+b;
显然是可以的,但是如果运算对象是类发话不能直接用加号运算,
people1+people2显然是错误的
因为类里面信息很多,得指出来是具体的哪几项相加
#include<iostream>
#include<string>
using namespace std;
class l
{
public:
string name;int age;
l(string name,int age):name(name),age(age){}
l /*指针函数*/ operator+/*重载代替函数名*/(const l &/*表示常量引用*/p)
//上句返回值一般写成l &(被赋值对象的引用)
//返回时少调用一次拷贝函数,提高效率,可以实现连续的赋值
{
this->name=p.name+this->name;
this->age=p.age+this->age;
cout<<"ppp"<<endl;
return *this;
}
};
int main()
{
l p1("aaa",16);
l p2("bbb",17);
l p3=p1+p2;
cout<<p3.name<<' '<<p3.age<<endl;
return 0;
}
//地址上的取值需要用->,类对象取值用.
const int a=7;
int b=a;//正确
a=8;//错误
- 该值不允许修改,对const的定义可以给编译器帮助
- 即是通过地址修改也不能改变const的值,地址值会改变,但是输出a还是const定义的值
- 如果想要编译器知道改指针的情况,可以在他的前面加上volatile,volatile const 这不是有病吗
- const修饰指针变量有一下三种情况:
- a、修饰指针指向的内容,则内容不可变
const int *p=8;
- b、修饰指针,指针不可变
int a=8;
int *const p=&a;
- c、修饰指针和指向的内容,二者都不可变
int a=8;
const int *const p=&a;
- 左定值右定向,const修饰不变量
- 对于const修饰函数的情况就分为三种:
- a、值传递的const修饰传递,在函数内部也不能被改变
void print(const int a)
{
cout<<a;
a++;//错误
}
- b、当const修饰的是指针时可以防止指针被意外篡改
void print(int *const a)
{
*a=9;
}
int main()
{
int a=8;
print(&a)
cout<<a<<endl;//a为9
}