Search K
Appearance
前排提示:只涉及最传统的cpp特性,对于STL等更是只字不提(╥_╥)
[1,18]内联函数 (inline function)
[1.19]const
[1.21]引用
[1.22]向上造型
[1.23]多态
[1.24]多态实现
[1.25]引用再研究
[1.26]拷贝构造Ⅰ & [1.27]拷贝构造ⅠⅠ
[总结]
[1.28]静态对象 & [1.29]静态成员
[1.30]运算符重载
[1.34]模板(templates)
[1.36]异常
Only declarations are allowed to be in .h
进入scope时即对 对象分配空间 构造函数在定义类的对象时运行 析构(~)函数在对象离开scope时运行
struct Y{
int x;
float i;
Y(int c);
};
Y y1[]={Y(1),Y(2),Y(3)};class Time{};
void(Time:: * p3)(); // 指向Time类公用成员函数的指针变量p3
p3 = &Time::get_time; // 使p3指向Time类公用成员函数get_time
(t1.*p3)(); //调用对象t1中p3所指的成员函数(即t1.get_time( ))int Box∷volume( ){return(height*width*length);}
//
int Box∷volume(Box *this){
return(this->height * this->width * this->length);
//return((*this).height * (*this).width * (*this).length);
}
//调用: a[0].volume(&a[0]);new int;
new int[10];
new Stash; //分配空间,再构造函数
delete p; //析构函数,再收回空间
delete []p;
int *psome=new int [10];
delete []psome;struct X; //前项声明
struct Y{
void f(X* );
};
struct X{
private:int i;
public:
friend void Y::f(X* );
friend struct Z;
friend void h();
}initialized lists: A() :i(0)
class A{
public:
A(int ii):i(ii){};
private:
int i;
};
class B: public A{
public:
B():A(15){};
}protected :子类只能在类中使用父类protected 的函数,不能在main 中使用inline关键字,与一般函数不同,必须在.h文件中同时包括声明和定义TIP
原因:编译器只同时处理一个编译单元
inline关键字int Date::get_day() const {
}INFO
常对象
Time const t1(12,34,46);
//t1是常对象 ⇔
const Time t1(12,34,46);常类成员
mutable关键字
mutable int cnt;cntchar& r=c;const int &z=x;
//不能通过z修改xint &*p; //illegal! No pointers to reference
int *&p; //legal!#include<iostream>
using namespace std;
class A{
public:
int i;
A():i(10){}
};
class B: public A{
private:
int j;
public:
B():j(20){}
void f(){cout<<"B.j="<<j<<endl;}
};
int main(){
A a;
B b;
cout<<a.i<<" "<<b.i<<endl;
b.f();
int *p= (int *)(&a);
int *q= (int *)(&b);
*p=100;
cout<<"!"<<"a.i="<<a.i<<endl;
*q=200;
cout<<"!"<<"b.i="<<b.i<<endl;
q++;
*q=2000;
b.f();
return 0;
}Virtual关键字:class Shape{
public:
Shape ();
virtual ~Shape();
virtual void render();
}
class Ellipse : public Shape(){
Ellipse(float maj,float minr); //构造函数
virtual void render();
……
}
Ellipse ell(10,20); //定义对象
void render(Shape *p){
p->render();
}Shape类被继承时,对于virtual关键字的函数,子类的同名函数与其产生联系。 这时子类同名函数virtual关键字 可加可不加Shape将具有许多子类。render()画出图形virtual作用 virtual: 根据[[#[1.22]向上造型]],调用render(&ell)会调用Shape的render().virtual: 程序在运行时进行检查,调用正确的render()函数INFO
C++的一切都可以用C来实现
virtual时,对象的首地址为vptr
class A{};
class B: public A {};
A a;
B b;
A *p= &b;
p->f();
// a=b; 这是合法的,但是vptr不参与赋值virtual的,将调用b.f(),否则a.f()A *p= new B;
delete p;virtualclass X{
public:
int &my;
X(int &a); //注意构造函数接收的引用
}
X::X(int &a):my(a){};void func(int &);
func(i*3); //error 所传的东西需要能做左值形式:
class A{
public:
A(const A &){}
};void func(A a){};
func(x); //发生拷贝构造截至目前,创建一个类时需要
main之前调用,程序结束时析构 ⚠️不同文件的全局的对象初始化顺序未定义initialized list只能对非静态成员初始化类名::访问 因此,静态的成员变量/函数可理解为类的属性,在对象定义之前就可以访问它们,因为是“属于类的”可被重载的运算符:existing operators
函数名:operator"被重载的运算符“
example:`const String String::operator +(const String& that)
consider:
const,函数是否const可维护性:实践中当同时重载一系列运算符时,常常通过调用重载过的运算符来实现(如重载=与!=时,后者调用前者)。而inline保证性能不损失
重载赋值:
return *this 一种写法:T & T::operator=(const T & rhs){
if (self != rhs){ //! 当类中包含指针操作时,不判断可能出错
//赋值
}
return *this;
}private重载赋值号,使该类对象无法被赋值类型转换
INFO
class A{
public:
A() {};
};
class B{
public:
B(const A &) {} // !
};
void f(B) {}
int main(){
A a;
f(a); //编译器能够用a先构造B作为f的参数
}explicit关键字,则B构造函数必须显式情况下被调用,即f(B(a))显式转换:
X::operator T()WARNING
上述两种转换方式不能同时具有,否则编译器不知道使用哪一个
We use templates to write generic code that is manageable, type-safe, and flexible across different data types.
int, double, etc.), templates allow us to define a single "blueprint."EXAMPLE>_<
Function Template:
template <typename T>
void swap(T &x, T &y) { // Pass by reference to allow modification
T temp = x;
x = y;
y = temp;
}template keyword indicates that the following block is a template.T is a placeholder for a type.float i = 4.5, j = 3.7;
swap(i, j); // The compiler deduces that T is floatswap(i, j) is called, the compiler generates a concrete version of the function for the float type. This process is called instantiation.EXAMPLE>_<
Class Template:
template <class T>
class Vector{
public:
Vector(int);
~Vector();
Vector(const Vector &);
//……
private:
T *m_elements;
int m_size;
}
//all functions inside the class template are function templates
template
Vector<T>::Vector(int size):m_size(size){
m_elements = new T[m_size];
}
//main
Vector<int> v1(100); //use the class template函数模板内涉及大小比较时,希望比较对象适用于任何类型(generic type),涉及重载运算符
命名generic type时,习惯首字母大写(cpp默认类型int等均为小写)
template参数除了generic type,可以有默认参数
template<class T,int bounds=100>
嵌套
继承:继承自一个具体的类,而不是模板继承模板
程序的异常大致可以分为两种:编译的error与运行时出错。尽管C++的设计角度能够在error层面做更多的排查,但后者依然是程序的主要问题原因。
if-else判断,依赖返回值判断(读取,写入)等等操作是否正常进行但这种方式的问题也很显然:可读性大大降低,嵌套if-else使程序逻辑不清晰
DEFINITION (๑˃ᴗ˂)ﻭ
throw关键字 首先是中止当前函数运行
例如,在一个数组index越界的问题中
//类模板
template <class T> class Vector{
private:
T* m_elements;
int m_size;
public:
Vector(int size=0):m_size(size){}
~Vector(){ delete [] m_elements;}
void length(int);
int length(){ return m_size;}
T& operator[](int); //需要异常处理
};
//
template <class T>
T & Vextor<T>::operator[](int indx){
if(indx<0 || indx >= m_size){
//VectorIndexError e(indx);
//throw e;
throw VectorIndexError(indx);
//函数不知道如何处理异常,所以抛出(throw)到外部
}
return m_elements[indx];
}
//a class to represent the error
class VectorIndexError{
public:
VectorIndexError(int v): m_badValue(v){}
~VectorIndexError(){}
void diagnostic(){
cerr << "index" <<m_badValue<<"out of range!" ;}
private:
int m_badValue;
}当throw触发后,进行以下循环:
它所在语句(起初是if-else块)在此中止
检查throw是否在try块内
catch是否匹配//越界产生的函数
int func(){
Vector<int> v(12);
v[3]=5;
int i=v[42]; //throw happens!
return i* 5;
}
void outer(){
try{
func(); func2(); //根据throw原则,func2()不被执行
}catch(VectorIndexError& e){
e.diagnostic();
}
}catch内部进一步throw(语句后无对象,仍然处理当前异常对象)catch(…) //此为关键字 :捕获任意异常//catch可以有多个
try{
}catch(){
}catch(){
}catch(){
}void abc(int a):throw(MathErr){
//限制此函数最多能抛出"MathErr"异常
}未完待续……(⁄ ⁄•⁄ω⁄•⁄ ⁄)