classgoodgay { public: voidvisit(); //access public & private in building class goodgay();
building *b; };
classbuilding {
friendclassgoodgay;
public: building();
char m_sittingroom;
private: char m_bedroom; };
//declare the member function out the class building::building() { m_sittingroom = 's'; m_bedroom = 'b'; }
goodgay::gay() { //create building obj //building *b; in goodgay class b = new building; }
voidgoodgay::visit() { out << b->m_sittingroom << '\n'; }
1 2 3 4 5
voidtest() { goodgay gg; gg.visit(); }
This example mainly describes how to declare member function out of the class.
1.3. Member function as the friend
friend void goodgay::visit();, declare out of the class.
2. Member Feature
2.1 Member Variable & Member function
1 2 3 4 5
classx {
};
An empty obj consumes one byte memory.
1 2 3 4 5 6 7
classx { int m_x1; // not static staticint m_x2; // static voidfun(){} };
If an obj is not empty, for example the upper class consumes 4 byte as the static variable is not belonged to the class and the member function is saved separately , which not belongs to the obj of the class either.
2.2 This Pointer
The this pointer points to the invoked obj of the class, solves the name conflict and return the obj itself.
2.2.1 Solve the Name Conflict
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classExample { public: Example(int num) { num = num; } // this is the wrong constructor function
Example(int num) { this->num = num; }// this one is right
int num; };
1 2 3 4 5 6
voidtest01() { Example ex(10); std::cout << ex.num; }
voidtest03() { Example ex1 = 10, ex2 = 10; //The return value is void, the compiler will report error. ex2.ExampleAddNum(ex1).ExampleAddNum(ex1).ExampleAddNum(ex1); std::cout << ex2.num; }
If you want to add multiple times, you need to return the this pointer.
/*you need to return the & else the condition will be like the first time: ex2`.ExampleAddNum(ex1).ExampleAddNum(ex1) the second time: ex2``.ExampleAddNum(ex1) in other words, each time the function is invoked, a new ex2(obj) will be generated. */ Example& ExampleAddNum(Example &in_ex) { this->num += in_ex.num return *this; }
int num; };
2.3 nullptr Access the Member function
In the c++, the nullptr can access the member function.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
Class Example { voidShowClassName() { std::cout << "Example\n"; }
voidtest01() { Example *p = nullptr; p->ShowClassName();//will not report error p->ShowExampleNum();//will report error }
In the p->ShowExampleNum(); the inputted pointer is nullptr.As the real effect in this function is std::cout << this->m_num << std::endl;.The this pointer is nullptr. If you do not want the error,you can add if(this == nullptr)return;
2.4. const member function
Const function:
const function cannot change the member attribute
adding the “mutable” key words when decare member attribute, it can be changed in the const function.
Const obj: can only invokes the const function
2.4.1 Const function
1 2 3 4 5 6 7 8 9 10 11
classExample { public: voidshowExample()const { m_A = 100; //ACTUALLY it is this->m_A = 100; }
int m_A; };
The this pointer is a pointer const, it can not be changed where it points at. The showExample function actually means const Example* const this, the pointed value can thus not be changed.The const added after the function means the point of the pointer is const, so the pointed value can not be changed.
2.4.2 Const obj
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classExample { public: voidshowExample()const { m_A = 100; //ACTUALLY it is this->m_A = 100; }
voidchange() { m_A = 100; }
int m_A; mutableint m_B };
Now the value of m_B can be changed in the const function.
The print consequence will be 200, which is the subclass member variable.If you want to access the parent class member, use b.A::a. When it comes to the same name member function, useb.A::func(), the same as the overloaded function, as the subclass hides the same name function in parent class.
3.6 Process of Same Name Static Member
1 2 3 4 5 6 7 8 9 10 11 12 13
classbase { public: staticint m_A; }; int base::m_A = 100;
classsub: public base { public: staticint m_A; }; int sub::m_A = 200;
voiddo_speak(Animal &an) { an.speak(); } //According to the tips above, you don not need to change the type //Animal & animal = cat voidtest() { Cat cat; do_speak(cat) }
In this case the result is “Animal talking” as the address is early bound. The func`s address should not be early bound if you want realize different functions.
Adding the key word virtualcan realize different function and the address of the speak function is late bound.The sub class need to rewrite the virtual function in the base class.Not overload. When the base class reference(&) or pointer(*) point at the obj of sub class can you use dynamic polymorphism.
sizeof(Animal) = 4. 4 bytes ~ virtual function pointer(vfptr). Vfptr contains the Virtual Function Table(vftable) that contains the address of the virtual function. In the Animal Class, vfptr -> vfable( &Animal::speak( ) ). In the Cat, if the virtual has not been written, then vfptr -> vfable( &Animal::speak( ) ). While the rewritten virtual function covers the virtual function of base class. So now, vfptr -> vfable( &Cat::speak( ) ).
4.3 Abstract Class
If class include more than one(include) Pure Virtual Function, we call te class abstract class.Pure Virtual Function: virtual void func() = 0.
The base class is unable to instantiate.
The sub class must written the pure virtual function.
4.4 Virtual Destruction Function
When using the pointer in base class point at the obj in sub class, the pointer will not do invoke the destruction function in the sub class. By using virtual ~name(), the destruction function will be invoked. The virtual and pure virtual destruction function ned to be realized as the base class may also have memory in the heap area.
1 2 3 4 5 6 7 8 9 10
classAnimal { public: virtual ~Animal() = 0; }
Animal::~Animal() { cout << "The destruction of Animal"; }