可变形参:用户可以传递有限的任意个的实参。
eg: printf(char*,...);
函数:用于操作实参栈区。
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);
定义可变形参:
返回值 函数名/方法名(形参1,形参2,...)
注:形参1,形参2代表固定形参, ...可变形参
work:实现仿照printf来实现打印(打印到屏幕时可以借助cout)
(必须实现)
myprintf("hello world %d %s %f %c\n",100,"wuhan",99.9,'m');
屏幕: hello world 100 wuhan 99.9 m
//提升
myprintf("hello world %03d %s %.1f %c\n",100,"wuhan",99.9,'m');
注:类型提升 char->int short->int float->double
友元函数:一个外部函数不能访问某类的非公成员时,可以声明为友元函数。
友元类:一个对象A想去访问另一个类对象B的非公有成员时,可以声明为友元类。
声明为友元类:
class B
{
...
friend class 类名;
...
};
class A
{
...
};
继承:从已有的类派生一个新类,新类保持原有类的特性。
子类(派生类):从一个已经类派生出的一新类
父类 :继承给子类的类
class 父类
{
...
};
class 派生类:派生方式 父类1,派生方式 父类2...
{
};
派生方式:公有派生,保护派生,私有派生。
公有派生:
父类 子类
private private
public public
procted procted
保护派生:
父类 子类
private private
public procted
procted procted
私有派生:
父类 子类
private private
public private
procted private
1、总结
1、C++是不会选择继承,全部继承。
2、也就是派生类中,有了父类的特性(成员方法和成员变量都是派生的成员),除了构造函数与析构函数是不会派生的。
3、(*)子类是不能直接访问父类继承过来的私有成员,但子类可以间接访问父类继承非私有的接口。
4、对子类对象释放时,为了结束继承过来部分,也会发送基类析构消息用于释放基类空间
子类初始化:不仅构造自己新增的特性,还需要初始化构造继承的部分。可以间接向父类发送构造消息。
(由于继承部分(私有)不能直接访问,也不会直接调用构造函数,父类的构造方法与析构是不会被继承)
子类的构造方法通过初始化列表来初始父类
子类构造方法(形参列表):父类构造方法(实参列表),...
{
}
注:1、若子类不显示的初始化继承的父类部分,编译器会默认添加调用默认构造函数。
2、构造:先父类初始化,再初始化自己、
3、析构:先子类再父类
2、重载:在同一作用域下,存在多个相同的函数名但形参不同。
3、重写(覆盖):
方法
当父子类出现同名方法时,子类的方法的作用域覆盖父类的方法(作用域)
子类优先
注:覆盖只是作用域被覆盖,但是父类的方法还是存在。可以通过作用域来进行访问。
变量:如果父子类同名的变量时,子类优先
应用场景:当基类方法不太满足子类功能要求时,重新定义此方法。
4 二义性:在一个子类中,如果父子类中出现同名现象。
1、解决方案:作用域
子类.作用域::成员;
5、父子类型之间赋值/复制:
注:不同类型不能互相赋值。同类型对象之间可以相互赋值。(内存空间相同)
只能由子类对象赋值给父类(子类对象中有父类的空间),不能由父类赋值给子类
6多继承:
*多重继承:由多个父类派出一个子类。
class 派生类:继承方式 父类1,继承方式 父类2,,,
{
};
实例化:由于继承部+新增部分,故初化时不仅初始化新部分,还需要初始化继承部分
继承部分:由父类的构造方法对其初始化
派生类的构造函数(...):父类1(...),父类2(...),,,
{
}
注:若不显示的去调用父类构造方法时,编译器会默认添加
构造时:先父类,再子类,(如果是隐式的构造,则调用父类构造顺序由于继承列表决定;反之,则初始化列表来决定)
析构时:与调用顺序相反。(先子类,再父类)
重写:父子类中出现同名现象,子类的作用域覆盖父类的同名成员:
作用域解决
多层继承:
类A
{
};
类B:public A
{
};
类C:public A
{
int a;
};
类D:public B,public C
{
...
int a;
};
A->B->D->E
D d;
d.C::a; //通过作用域解决问题
总结方式:
1、单继承:不会造成二义性。
2、多继承:冗余问题(尽量避免出现:菱形继承(通过指定虚基类来解决冗余问题))
虚基类:解决菱形继承的冗余问题。
class A
{
...
};
class B:viartual 继承方式 A
{
...
};
class C:viartual 继承方式 A
{
...
}
class D:继承方式 B,继承方式 C
{
。。。
};
公共基类:一个派生类中,出现多个同基类时。
问题:二义性,多次分配公共基类
解决:虚基类(本质:由于继承不能选择性继承,导致出现多次公共基类的部分)只保留一次的公共基类的部分。
类A ---公共基类
{
};
类 B:virtual 继承方式 类A
{
}
类C:virtual 继承方式 类B
{
}
类D:类C ,类D
{
};
注:类中的公共基类部分,不能类B与类C初始化,只能公共基类的构造方法初始化。
栈:FILO
栈顶:只允许一端操作
栈底:不允许操作的一端
顺序栈:栈中元素存放在数组中
缺点:存储长度有限制
链表栈:通过链表思想来完成栈(FILO)
eg: printf(char*,...);
函数:用于操作实参栈区。
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);
定义可变形参:
返回值 函数名/方法名(形参1,形参2,...)
注:形参1,形参2代表固定形参, ...可变形参
work:实现仿照printf来实现打印(打印到屏幕时可以借助cout)
(必须实现)
myprintf("hello world %d %s %f %c\n",100,"wuhan",99.9,'m');
屏幕: hello world 100 wuhan 99.9 m
//提升
myprintf("hello world %03d %s %.1f %c\n",100,"wuhan",99.9,'m');
注:类型提升 char->int short->int float->double
友元函数:一个外部函数不能访问某类的非公成员时,可以声明为友元函数。
友元类:一个对象A想去访问另一个类对象B的非公有成员时,可以声明为友元类。
声明为友元类:
class B
{
...
friend class 类名;
...
};
class A
{
...
};
继承:从已有的类派生一个新类,新类保持原有类的特性。
子类(派生类):从一个已经类派生出的一新类
父类 :继承给子类的类
class 父类
{
...
};
class 派生类:派生方式 父类1,派生方式 父类2...
{
};
派生方式:公有派生,保护派生,私有派生。
公有派生:
父类 子类
private private
public public
procted procted
保护派生:
父类 子类
private private
public procted
procted procted
私有派生:
父类 子类
private private
public private
procted private
1、总结
1、C++是不会选择继承,全部继承。
2、也就是派生类中,有了父类的特性(成员方法和成员变量都是派生的成员),除了构造函数与析构函数是不会派生的。
3、(*)子类是不能直接访问父类继承过来的私有成员,但子类可以间接访问父类继承非私有的接口。
4、对子类对象释放时,为了结束继承过来部分,也会发送基类析构消息用于释放基类空间
子类初始化:不仅构造自己新增的特性,还需要初始化构造继承的部分。可以间接向父类发送构造消息。
(由于继承部分(私有)不能直接访问,也不会直接调用构造函数,父类的构造方法与析构是不会被继承)
子类的构造方法通过初始化列表来初始父类
子类构造方法(形参列表):父类构造方法(实参列表),...
{
}
注:1、若子类不显示的初始化继承的父类部分,编译器会默认添加调用默认构造函数。
2、构造:先父类初始化,再初始化自己、
3、析构:先子类再父类
2、重载:在同一作用域下,存在多个相同的函数名但形参不同。
3、重写(覆盖):
方法
当父子类出现同名方法时,子类的方法的作用域覆盖父类的方法(作用域)
子类优先
注:覆盖只是作用域被覆盖,但是父类的方法还是存在。可以通过作用域来进行访问。
变量:如果父子类同名的变量时,子类优先
应用场景:当基类方法不太满足子类功能要求时,重新定义此方法。
4 二义性:在一个子类中,如果父子类中出现同名现象。
1、解决方案:作用域
子类.作用域::成员;
5、父子类型之间赋值/复制:
注:不同类型不能互相赋值。同类型对象之间可以相互赋值。(内存空间相同)
只能由子类对象赋值给父类(子类对象中有父类的空间),不能由父类赋值给子类
6多继承:
*多重继承:由多个父类派出一个子类。
class 派生类:继承方式 父类1,继承方式 父类2,,,
{
};
实例化:由于继承部+新增部分,故初化时不仅初始化新部分,还需要初始化继承部分
继承部分:由父类的构造方法对其初始化
派生类的构造函数(...):父类1(...),父类2(...),,,
{
}
注:若不显示的去调用父类构造方法时,编译器会默认添加
构造时:先父类,再子类,(如果是隐式的构造,则调用父类构造顺序由于继承列表决定;反之,则初始化列表来决定)
析构时:与调用顺序相反。(先子类,再父类)
重写:父子类中出现同名现象,子类的作用域覆盖父类的同名成员:
作用域解决
多层继承:
类A
{
};
类B:public A
{
};
类C:public A
{
int a;
};
类D:public B,public C
{
...
int a;
};
A->B->D->E
D d;
d.C::a; //通过作用域解决问题
总结方式:
1、单继承:不会造成二义性。
2、多继承:冗余问题(尽量避免出现:菱形继承(通过指定虚基类来解决冗余问题))
虚基类:解决菱形继承的冗余问题。
class A
{
...
};
class B:viartual 继承方式 A
{
...
};
class C:viartual 继承方式 A
{
...
}
class D:继承方式 B,继承方式 C
{
。。。
};
公共基类:一个派生类中,出现多个同基类时。
问题:二义性,多次分配公共基类
解决:虚基类(本质:由于继承不能选择性继承,导致出现多次公共基类的部分)只保留一次的公共基类的部分。
类A ---公共基类
{
};
类 B:virtual 继承方式 类A
{
}
类C:virtual 继承方式 类B
{
}
类D:类C ,类D
{
};
注:类中的公共基类部分,不能类B与类C初始化,只能公共基类的构造方法初始化。
栈:FILO
栈顶:只允许一端操作
栈底:不允许操作的一端
顺序栈:栈中元素存放在数组中
缺点:存储长度有限制
链表栈:通过链表思想来完成栈(FILO)