C++
面向对象编程
面向对象编程的三大特性分别为:封装、继承、多态.
属性和行为
封装主要指对属性和行为的封装.
封装的语法:
1 2 3 4 5 class 类名{访问权限: 属性(成员变量) 行为(成员函数) };
其中访问权限一共有三类:public、private、protected.
举个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include <iostream> using namespace std;class Hero { public : int m_Id; int m_Hp; void addHp (int hp) { m_Hp += hp; } void subHp (int hp) { m_Hp -= hp; } }; int main () { Hero h; h.m_Id = 0 ; h.m_Hp = 100 ; h.addHp (100 ); cout << "HP:" << h.m_Hp << endl; h.subHp (100 ); cout << "HP:" << h.m_Hp << endl; system ("pause" ); return 0 ; }
通过类来生成对象的过程,叫做实例化 .
访问权限
访问权限一共有三种:
公共权限 public 类内可以访问,类外也可以访问
保护权限 protected 类内可以访问,类外不可以访问 子类可以访问
私有权限 private 类内可以访问,类外不可以访问 子类不可以访问
B —> A B继承于A类,则 A为父类、基类。B类为子类、派生类. 其中子类B是可以访问A类的保护成员,无法访问A类中私 有权限的成员.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <iostream> using namespace std;class People { public : int m_Id; protected : int m_HouseId; private : int m_Paypass; public : void work () { m_Id = 1 ; m_HouseId = 2 ; m_Paypass = 1314 ; } }; class son : public People { void work1 () { m_Id = 1 ; m_HouseId = 2 ; m_Paypass = 1314 ; } }; int main () { People p; p.m_Id = 1 ; p.m_HouseId = 3 ; p.m_Paypass = 333 ; return 0 ; }
class和struct
struct 的权限默认是公共的 ,class 的权限默认是私有的 .
c++中的struct是可以定义成员函数的,而c 里的struct是无法定义成员函数的. 这是c 和c++ 中struct的区别.
所以c++中 class和struct的区别只有访问权限的区别.
属性私有化
属性变成私有以后,可以通过一些函数、方法、接口的方式来控制它的读写权限.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 #include <iostream> #include <string> using namespace std;class Student { public : void SetName (string name) { m_Name = name; } string GetName () { return m_Name; } string GetGender () { return m_gender; } void SetRank (int rank) { if (rank <= 0 || rank > 50 ) { cout << "rank is not legal" << endl; return ; } m_rank = rank; } private : string m_Name; string m_gender = "male" ; int m_rank; }; int main () { Student s; s.SetName ("dong" ); cout << s.GetName () << endl; cout << s.GetGender () << endl; s.SetRank (1 ); system ("pause" ); return 0 ; }
构造函数
实例化对象时需要对对象初始化,这些初始化就是在构造函数中进行的.
构造函数特点:
函数名称和类名保持一致
不需要写返回值类型
构造函数可以有参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #include <iostream> #include <string> using namespace std;class Student { public : Student () { m_Name = "" ; m_gender = "male" ; m_rank = 1 ; cout << "default constructor function" << endl; } Student (string name) { m_Name = name; m_gender = "male" ; m_rank = 1 ; cout << "parameterized constructor function" << endl; } private : string m_Name; string m_gender; int m_rank; }; int main () { Student s1; Student s2 ("dong" ) ; Student s3 () ; Student s4{}; Student s5 = Student ("dong" ); system ("pause" ); return 0 ; }
析构函数
析构函数和构造函数是相对的,构造函数是对对象进行初始化,析构函数是对对象进行反初始化(数据清理).
析构函数在对象被销毁前是由系统自动调用的.
析构函数名 同样和类名一致,在最前面加上一个~
函数无返回值
不能有参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include <iostream> #include <string> using namespace std;class Student { public : Student () { cout << "default constructor function" << endl; } ~Student () { cout << "destructor function" << endl; } }; int main () { { Student s1; } system ("pause" ); return 0 ; }
拷贝构造函数
拷贝构造函数目的使用一个对象构造出另一个对象.
拷贝构造函数定义:
引用确保传参时不会多一次拷贝,const确保传进来的参数不会被改变
拷贝构造函数调用时机:
用已经创建的对象来初始化对象、
函数的传参
函数的返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 #include <iostream> #include <string> using namespace std;class Student { public : Student () { cout << "default constructor function" << endl; } Student (string name) { m_Name = name; cout << "parameterized constructor function" << endl; } Student (const Student &student) { m_Name = student.m_Name; cout << "copy constructor function" << endl; } ~Student () { cout << "destructor function" << endl; } private : string m_Name; }; void func1 () { cout << "---------------func1----------------" << endl; Student s1 ("dong" ) ; Student s2 (s1) ; } void test1 (Student s) {} void test2 (Student *s) {} void func2 () { cout << "---------------func2----------------" << endl; Student s3; test1 (s3); test2 (&s3); } Student test3 () { Student s4 ("liu" ) ; return s4; } void func3 () { cout << "---------------func3----------------" << endl; Student s = test3 (); } int main () { func1 (); func2 (); func3 (); system ("pause" ); return 0 ; }
初始化列表
初始化列表是对对象初始化用的,语法如下:
1 构造函数():成员变量1 (传参1 ),成员变量2 (传参2 ){}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include <iostream> #include <string> using namespace std;class Student { public : Student (string name, int score) : m_Name (name), m_score (score) { } void Print () { cout << m_Name << " " << m_score << endl; } private : string m_Name; int m_score; }; int main () { Student s1 ("dong" , 100 ) ; s1. Print (); system ("pause" ); return 0 ; }
静态成员变量
静态成员变量特点:
所有的对象共享同一份数据
编译阶段分配内存
需要在类中进行声明,在类外进行初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include <iostream> #include <string> using namespace std;class Student { public : Student () { m_Name = "dong" ; m_Score = 100 ; } ~Student () { } static int m_StudentCount; private : string m_Name; int m_Score; }; int Student::m_StudentCount = 50 ;int main () { Student s1; cout << s1. m_StudentCount << endl; s1. m_StudentCount = 101 ; cout << Student::m_StudentCount << endl; cout << &(s1. m_StudentCount) << endl; cout << &(Student::m_StudentCount) << endl; return 0 ; }
静态成员函数
类比于静态成员变量,静态成员函数也是所有对象共享一个函数 . 并且静态成员函数只能用到静态成员变量 ,不能用普通成员变量.
所有对象共享函数
静态成员函数只能使用静态成员变量,无法使用普通成员变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include <iostream> #include <string> using namespace std;class Student { public : Student () { m_Name = "dong" ; m_Score = 100 ; } ~Student () { } static int m_StudentCount; static int GetStudentCount () { return m_StudentCount; } private : string m_Name; int m_Score; }; int Student::m_StudentCount = 50 ;int main () { Student s1; cout << s1. GetStudentCount () << endl; cout << Student::GetStudentCount () << endl; return 0 ; }
this指针
类里有个变量叫this, 主要用途如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include <iostream> #include <string> using namespace std;class Student { public : Student (int score) { this ->score = score; cout << this << endl; } int score; }; int main () { Student s1 (100 ) ; cout << s1. score << endl; cout << &s1 << endl; return 0 ; }
const修饰成员函数
成员函数的参数和函数体之间加上一个const叫做常函数 . 常函数的函数体中不能修改成员属性的值 .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <iostream> #include <string> using namespace std;class Student { public : Student () : score (100 ) {} int GetScore () const { return score; } int SetScore (int score) { this ->score = score; } private : int score; }; int main () { const Student s1; s1. SetScore (100 ); return 0 ; }
mutable关键字
为了让成员变量可以在常函数里修改,需要加入一个关键字即mutable.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <iostream> #include <string> using namespace std;class Student { public : Student () : score (100 ), counter (0 ) {} int GetScore () const { counter++; return score; } void printCounter () const { cout << "Counter:" << counter << endl; } private : int score; mutable int counter; }; int main () { const Student s1; s1. GetScore (), s1. GetScore (), s1. GetScore (); s1. printCounter (); }
友元
友元 的目的是让一个函数或者一个类能够访问另外一个类的私有成员 .
友元的关键字: friend
三种友元:
全局函数作为友元
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <iostream> #include <string> using namespace std;class Student { friend void test1 (Student *s) ; public : Student () : score (100 ), name ("dong" ) {} public : string name; private : int score; }; void test1 (Student *s) { cout << s->name << endl; cout << s->score << endl; } int main () { Student s1; test1 (&s1); return 0 ; }
类作为友元
让一个类去访问另一个类的私有成员.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include <iostream> #include <string> using namespace std;class Student { friend class Teacher ; public : Student () : score (100 ), name ("dong" ) {} public : string name; private : int score; }; class Teacher { public : Teacher () {} void visit (Student *s) { cout << s->score << endl; } }; int main () { Student s1; Teacher t1; t1. visit (&s1); return 0 ; }
成员函数作为友元
上面例子中是通过友元将Teacher类访问Student类的私有成员变量.
现在目的是 将Teacher类的成员函数 能够访问Student类的私有成员变量. 即成员函数作为友元 .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include <iostream> #include <string> using namespace std;class Student ;class Teacher { public : Teacher () {} void visit (Student *s) ; }; class Student { friend void Teacher::visit (Student *s) ; public : Student () : score (100 ), name ("dong" ) {} public : string name; private : int score; }; void Teacher::visit (Student *s) { cout << s->score << endl; } int main () { Student s1; Teacher t1; t1. visit (&s1); return 0 ; }
重载
同一个方法名,参数不同,表示同类功能的不同实现。
加号重载
成员函数的方式加号重载:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include <iostream> #include <string> using namespace std;class Complex { public : Complex () : real (0 ), image (0 ) { } Complex (int real, int image) { this ->real = real; this ->image = image; } Complex operator +(Complex &other) { Complex ret; ret.real = this ->real + other.real; ret.image = this ->image + other.image; return ret; } void Print () { cout << real << "+" << image << "i" << endl; } private : int real; int image; }; int main () { Complex a (1 , 2 ) ; Complex b (2 , 3 ) ; Complex c = a + b; c.Print (); return 0 ; }
全局函数方式加号重载:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <iostream> #include <string> using namespace std;class Complex { friend Complex operator +(Complex &a, Complex &b); public : Complex () : real (0 ), image (0 ) { } Complex (int real, int image) { this ->real = real; this ->image = image; } void Print () { cout << real << "+" << image << "i" << endl; } private : int real; int image; }; Complex operator +(Complex &a, Complex &b) { Complex ret; ret.real = a.real + b.real; ret.image = a.image + b.image; return ret; } int main () { Complex a (1 , 2 ) ; Complex b (2 , 3 ) ; Complex c = a + b; c.Print (); return 0 ; }
左移重载
左移的目的是把这个对象输出出来.Complex c;cout.operator<<(c)
但是成员函数重载应该是c在前面c.operator<<(cout) ,这才是成员函数的重载.
正常情况下是cout<<c, 但此时相当于是cout.operator<<©,即operator <<相当于cout的成员函数,会输出不出来定义的Complex c,因此需要<< 变为Complex类的成员函数,此时这种情况下实现就变成了c.operator<<(cout),仍然不是想要的cout<<c,因此需要从成员函数抽出来变成一个全局函数,然后全局函数作为友元声明,同时为了能够链式输出加上返回值类型ostream&.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 #include <iostream> #include <string> using namespace std;class Complex { friend Complex operator +(Complex &a, Complex &b); friend ostream &operator <<(ostream &cout, Complex a); public : Complex () : real (0 ), image (0 ) { } Complex (int real, int image) { this ->real = real; this ->image = image; } void Print () { cout << real << "+" << image << "i" << endl; } private : int real; int image; }; Complex operator +(Complex &a, Complex &b) { Complex ret; ret.real = a.real + b.real; ret.image = a.image + b.image; return ret; } ostream &operator <<(ostream &cout, Complex a) { cout << a.real << "+" << a.image << 'i' ; return cout; } int main () { Complex a (1 , 2 ) ; Complex b (2 , 3 ) ; Complex c = a + b; c.Print (); cout << c << endl; return 0 ; }
递增重载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #include <iostream> #include <string> using namespace std;class Complex { friend ostream &operator <<(ostream &cout, Complex a); public : Complex () : real (0 ), image (0 ) { } Complex (int real, int image) { this ->real = real; this ->image = image; } Complex &operator ++() { this ->real += 1 ; return *this ; } Complex operator ++(int ) { Complex c = *this ; this ->real += 1 ; return c; } private : int real; int image; }; ostream &operator <<(ostream &cout, Complex a) { cout << a.real << "+" << a.image << "i" ; return cout; } int main () { Complex a (10 , 10 ) ; cout << a << endl; cout << a++ << endl; cout << a << endl; return 0 ; }
赋值重载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 #include <iostream> using namespace std;class Student { public : Student () : m_data (NULL ) {} Student (int data) { m_data = new int ; *m_data = data; } ~Student () { if (m_data) { delete m_data; m_data = NULL ; } } Student &operator =(Student &h) { if (m_data) { delete m_data; m_data = NULL ; } m_data = new int ; *m_data = *h.m_data; return *this ; } int *m_data; }; int main () { Student s1 (1 ) ; Student s2 (2 ) ; cout << s1. m_data << endl; cout << s2. m_data << endl; s1 = s2; cout << s1. m_data << endl; cout << s2. m_data << endl; return 0 ; }
继承
继承的语法:
子类又叫做派生类,父类叫做基类. 当我们写了几个类,然后发现它们有些共性,把这些共性抽取出来实现一个新的类,这个新的类就叫做基类或者父类.然后将之前的类都来继承它,那两个类就成为子类或派生类.
继承方式
继承方式一共有三种:
同时访问权限也一共有3种,组合一下是3*3=9种. 也就是原本在父类里面的访问权限通过继承方式作用后到子类里面,访问权限就会改变,总共有9种权限了.
子类继承方式\父类访问权限
public
protected
private
public
public****
protected
无法访问
protected
protected
protected
无法访问
private
private
private
无法访问
中间的3*3代笔子类的访问权限.
构造和析构顺序
继承中,构造链里,先构造的后析构.
d->b->c->a ,那么构造析构顺序:a b c d d c b a
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #include <iostream> using namespace std;class Animal { public : Animal () { cout << "Animal Constructor" << endl; } ~Animal () { cout << "Animal Deconstructor" << endl; } }; class Cat : public Animal{ public : Cat () { cout << "Cat Constructor" << endl; } ~Cat () { cout << "Cat Deconstructor" << endl; } }; class BosCat : public Cat{ public : BosCat () { cout << "BosCat Constructor" << endl; } ~BosCat () { cout << "BosCat Deconstructor" << endl; } }; void test () { Animal a; } int main () { test (); return 0 ; }
输出:
1.test()中只有 a
Animal Constructor
Animal Deconstructor
2.test()中只有 b
Animal Constructor
Cat Constructor
Cat Deconstructor
Animal Deconstructor
3.test()中只有 c
Animal Constructor
Cat Constructor
BosCat Constructor
BosCat Deconstructor
Cat Deconstructor
Animal Deconstructor
同名属性访问
同名属性指父类和子类都一个名字相同的变量. 当子类继承父类并且有一个同名变量名的时候,并不会进行覆盖,需要用一个作用域访问即可.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include <iostream> using namespace std; class Animal { public: Animal() { m_data = 1; } int m_data; }; class Cat : public Animal { public: Cat() { m_data = 2; } int m_data; }; void test() { Cat c; cout << c.m_data << endl; // 2 cout << c.Animal::m_data << endl; // 1 } int main() { test(); return 0; }
同名函数访问
同名函数指父类和子类都一个名字相同的函数. 当子类继承父类并且有一个同名函数的时候,并不会进行覆盖,需要用一个作用域访问即可.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include <iostream> using namespace std;class Animal { public : Animal () { } void eat () { cout << "animal eat" << endl; } }; class Cat : public Animal{ public : Cat () { } void eat () { cout << "cat eat" << endl; } }; void test () { Cat c; c.eat (); c.Animal::eat (); } int main () { test (); return 0 ; }
多继承
多继承具体值一个子类继承多个父类.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 #include <iostream> using namespace std;class BaseA { public : int m_A; int m_Base; BaseA () : m_A (0 ), m_Base (1 ) {} }; class BaseB { public : int m_B; int m_Base; BaseB () : m_B (0 ), m_Base (2 ) {} }; class BaseC { public : int m_C; BaseC () : m_C (0 ) {} }; class Son : public BaseA, public BaseB, public BaseC{ }; int main () { Son s; s.m_A = 1 ; s.m_B = 2 ; s.m_C = 3 ; s.BaseA::m_Base = 1 ; s.BaseB::m_Base = 3 ; cout << sizeof (s) << endl; return 0 ; }
多态
多态分为静态多态和动态多态.
静态多态主要是函数重载和运算符重载.
动态多态主要是利用派生类和虚函数来实现一个运行时多态.
首先代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include <iostream> using namespace std;class Animal { public : void eat () { cout << "Animal eat" << endl; } }; class Cat : public Animal{ public : void eat () { cout << "Cat eat" << endl; } }; void eat (Animal &a) { a.eat (); } void test () { Cat c; eat (c); } int main () { test (); return 0 ; }
打印结果:
“Animal eat”
如何调用到子类的函数?这时候引入虚函数 的概念. 在父类函数前面加上Virtual关键字,就叫做虚函数.
如果子类重写这个函数,同时父类是个虚函数 ,那么子类对象转换成父类对象时,父类调用这个函数时候就会变成一个子类的函数了,如下面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 #include <iostream> using namespace std;class Animal { public : virtual void eat () { cout << "Animal eat" << endl; } }; class Cat : public Animal{ public : void eat () { cout << "Cat eat" << endl; } }; class Pig : public Animal{ public : void eat () { cout << "Pig eat" << endl; } }; void eat (Animal &a) { a.eat (); } void test () { Cat c; Pig p; eat (c); eat (p); } int main () { test (); return 0 ; }
打印结果:
Cat eat
Pig eat
多态表现在我的函数传参是个动物,但是传入不同的动物它能产生不同的行为.这个就叫做多态,如上面的例子.
纯虚函数和抽象类
有时候写代码会出现父类里面的函数没有任何实现,都需要子类去实现,也就是让子类去重写。纯虚函数的目的就是这个目的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include <iostream> using namespace std;class Animal { public : virtual void eat () = 0 ; }; class Cat : public Animal{ public : virtual void eat () { cout << "cat eat" << endl; } }; int main () { Cat a; a.eat (); return 0 ; }
虚析构和纯虚析构
虚析构主要解决内存泄漏的问题.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 #include <iostream> using namespace std;class BaseA { public : BaseA () {} ~BaseA () { cout << "BaseA 销毁了" << endl; } }; class SonA : public BaseA{ public : SonA () : m_Value (NULL ) { m_Value = new int (10 ); } ~SonA () { cout << "SonA 销毁了" << endl; delete m_Value; } int *m_Value; }; class BaseB { public : BaseB () {} virtual ~BaseB () = 0 ; }; BaseB::~BaseB () { cout << "BaseB 销毁了" << endl; } class SonB : public BaseB{ public : SonB () : m_Value (NULL ) { m_Value = new int (10 ); } ~SonB () { cout << "SonB 销毁了" << endl; delete m_Value; } int *m_Value; }; int main () { BaseA *a = new SonA (); delete a; BaseB *b = new SonB (); delete b; return 0 ; }