1. 類就可以看作一個struct,類的方法,可以理解爲通過函數指針的方式實現的,類對象分配內存時,只分配成員變量的,函數指針並不需要分配額外的內存保存地址。
2. c++中類的構造函數,就是進行內存分配(malloc),調用構造函數
3. c++中類的析構函數,就時回收內存(free)
4. c++是基於棧和全局數據分配內存的,如果是一個方法內創建的對象,就直接在棧上分配內存了。
專門在克隆時使用的構造函數,是構造拷貝函數,原型時“類名(const 類名&)",避免拷貝整個對象,在傳遞對象時,改爲傳遞指針,同時將構造拷貝函數設置爲私有這樣做到強制限制。
5. 成員變量爲私有,僅僅時編譯時起到保護左右,實際內存模型沒有變。
6. 繼承是在原有的父類的內存模型上,再添加自己的數據
#include <stdio.h>
#include <stdlib.h>
class TestClass {
public:
int a;
TestClass() {
a = 1;
printf("do constructor\n");
}
~TestClass() {
printf("do destructor\n");
}
TestClass(TestClass &src) {
a = src.a;
}
};
void test(TestClass al) {
printf("%d\n", al.a);
}
void test(TestClass *al) {
printf("%d\n", al->a);
}
int main(void) {
TestClass ac;
printf("after constructor call\n");
printf("=================================\n");
test(ac);
printf("after function call\n");
}
7. c++多態的實現方式:虛函數(virtual)+使用對象的指針調用:一個類的virtual函數會被分配一個全局數組,保存他們的地址。所有的這個類的對象共享。
如果是自己模擬實現override,實際就是要調用的實現使用函數指針,子類確定這些函數。
/*
* test.cpp
*
* Created on: 2015年5月24日
* Author: jme
*/
#include <stdio.h>
#include <stdlib.h>
// 1. 定義一個函數指針
typedef void (*testFunc)();
class Base {
public:
testFunc getHandler() {
return func;
}
// 函數指針
testFunc func;
};
void funcImpl_1() {
printf("funcImpl_1\n");
}
void funcImpl_2() {
printf("funcImpl_2\n");
}
class Sub1: public Base {
public:
Sub1(){
// 2. 子類設置函數指針值
func = funcImpl_1;
}
};
class Sub2: public Base {
public:
Sub2() {
this->func = funcImpl_2;
}
};
int main(void) {
Base *baseC;
Sub1 *upper = new Sub1();
Sub2 *lower = new Sub2();
baseC = upper;
baseC->func();
baseC = lower;
baseC->func();
}
c++的virtual語法:
/*
* test.cpp
*
* Created on: 2015年5月24日
* Author: jme
*/
#include <stdio.h>
#include <stdlib.h>
class Base {
public:
// 如果是
virtual void testFunc();
void testFunc2();
};
class Sub1: public Base {
public:
Sub1(){
}
virtual void testFunc();
void testFunc2();
};
class Sub2: public Base {
public:
Sub2() {
}
virtual void testFunc();
void testFunc2();
};
class Sub3: public Base {
public:
Sub3() {
}
void testFunc();
void testFunc2();
};
void Base::testFunc() {
printf("base testFunc\n");
}
void Base::testFunc2() {
printf("base testFunc2\n");
}
void Sub1::testFunc() {
printf("Sub1 testFunc\n");
}
void Sub1::testFunc2() {
printf("Sub1 testFunc2\n");
}
void Sub2::testFunc() {
printf("Sub2 testFunc\n");
}
void Sub2::testFunc2() {
printf("Sub2 testFunc2\n");
}
void Sub3::testFunc() {
printf("Sub3 testFunc\n");
}
void Sub3::testFunc2() {
printf("Sub3 testFunc2\n");
}
void callWithPointer(Base *baseC) {
// 因爲定義了虛函數, 同時是指針調用,會查虛表,確定具體的實現函數
baseC->testFunc();
}
void callWithoutPointer(Base baseC) {
// 雖然定義了虛函數, 但是是直接對象調用懂,不會查虛表。
baseC.testFunc();
}
void call2(Base *baseC) {
// 靜態覆蓋的實現,根據具體的類型來確定調用的是父類還是子類的
baseC->testFunc2();
}
int main(void) {
Sub1 s1;
Sub2 s2;
Sub3 s3;
callWithPointer(&s1);
callWithPointer(&s2);
callWithPointer(&s3);
printf("=================\n");
callWithoutPointer(s1);
callWithoutPointer(s2);
callWithoutPointer(s3);
printf("=================\n");
call2(&s1);
call2(&s2);
call2(&s3);
}