在dynamic_cast中(behind this post) , 我們提到 , 若derived class inherit virtual function from base class ,
若同樣以base class做為引數傳入 , 在C++中是沒辦法直接知道這個argument的實際type. (RTTI , run time type information)
在dynamic_cast中(behind this post) , 我們提到 , 若derived class inherit virtual function from base class ,
若同樣以base class做為引數傳入 , 在C++中是沒辦法直接知道這個argument的實際type. (RTTI , run time type information)
Although stringstream is very convenient to us ,
but sometimes we can also use c method to split the string.
ostringstream provides an interface to manipulate strings as if they were output streams.
因為ostringostream is inherit from ostream.
在class中 , 我們若想要宣告一個data member為static , 通常分為public 與 private,
若是public , 則代表這個class的所有object都共享這個 data member ,
Vector 是一種sequence container , 在vector中的元素 , 是依照strict linear sequence的方式在進行排列.
要宣告一個vector , 一般來說有4種方式 ,
Abstract class其實就像是一個interface , 通常是用來做為其他class的base class ,
在C++中 , Abstract class至少要包含一個pure virtual function .
要進行operator overloading , 一般來說有兩種形式 , 分別是non-member function 以及 nonstatic member function .
non-member function一般來說較為容易理解 , 但是若要讓他能夠存取class內的private data , 則要將他宣告為friend function.
在C++中 , 我們可以藉由呼叫 virtual function來dispatch到我們想要呼叫的那個class功能 ,
class Feature
{
virtual void intersectWith(Feature* f) = 0;
virtual void intersectWith(Circle* f) = 0;
virtual void intersectWith(Square* f) = 0;
};
class Circle : public Feature
{
void intersectWith(Feature* f){ cout << "This is Feature in the Circle!!"; }
void intersectWith(Circle* f){ cout << "This is Circle!!"; }
void intersectWith(Square* f){ cout << "This is Square in the Circle!!"; }
};
class Square : public Feature
{
void intersectWith(Feature* f){ cout << "This is Feature in the Square!!"; }
void intersectWith(Circle* f){ cout << "This is Circle in the Square!!"; }
void intersectWith(Square* f){ cout << "This is Square!!"; }
}
以上面這個例子來說 , 若:
Feature* f1 = new Circle();
Feature* f2 = new Square();
Feature* f3;
此時我們若呼叫:
f1.intersectWith(f3);
f2.intersectWith(f3);
則分別會print出 This is Feature in the Circle!! 以及 This is Feature in the Square!!
這是由於virtual function會在run time時依照virtual table所記錄的內容自動幫我們動態決定應該要dispatch到哪一個class type.
但是若我們呼叫:
Feature* f3 = new Circle();
Feature* f4 = new Square();
f1.intersectWith(f4);
f2.intersectWith(f3);
照理說 , 我們想要印出的是 : This is Square in the Circle!! 以及 This is Circle in the Square!!
可是結果卻一樣是印出 This is Feature in the Circle!! 以及 This is Feature in the Square!!
這是由於argument的型別是在compile time時 , function overloading就已經幫我們決定好要使用哪個method function.
由於f1 以及 f2的type都是Feature* , 所以就會使用到argument為Feature*的那個method function.
如果我們要印出想要的內容 , 其時也很簡單 , 只要在動態決定一次就好了 , 而這就形成了double dispatching.
我們先要把intersectWith(Feature*) 這個virtual function的內容改為:
class Circle : public Feature
{
void intersectWith(Feature* f){ f.intersectWith(*this); }
void intersectWith(Circle* f){ cout << "This is Circle!!"; }
void intersectWith(Square* f){ cout << "This is Square in the Circle!!"; }
};
class Square : public Feature
{
void intersectWith(Feature* f){ f.intersectWith(*this); }
void intersectWith(Circle* f){ cout << "This is Circle in the Square!!"; }
void intersectWith(Square* f){ cout << "This is Square!!"; }
};
同樣呼叫:
Feature* f3 = new Circle();
Feature* f4 = new Square();
f1.intersectWith(f4);
f2.intersectWith(f3);
在第一次的dispatch中 , 我們會知道f2與f1是哪個class type , 此時我們會進到 void intersectWith(Feature* f){ f.intersectWith(*this); }
此時又進行一次的dispatch , 我們便會知道f4與f3是屬於哪個class type ,
因此最後便會印出:
This is Circle in the Square!! 以及 This is Square in the Circle!!
ref : http://en.wikipedia.org/wiki/Double_dispatch
在C++ 中 , 有兩種初始化的方式 , 分別是explicit initialization 與implicit initialization.
int
nValue = 5;
// explicit assignment
More specifically, composition is used for objects that have a has-a relationship to each other.
A car has-a metal frame, has-an engine, and has-a transmission.
Container , 其實就是一種容器 , 而Container class就是一種class , 但是這個class是可以用來裝其他class.
像array其實就是一種container 的例子.
The virtual table is a lookup table of functions used to resolve function calls in a dynamic/late binding manner.
every class that uses virtual functions (or is derived from a class that uses virtual functions) is given it’s own virtual table.
In general having getters and setters is showing poor abstraction, don't do it.
Getters and setters provide an illusion of encapsulation,
Compile time指的是compile進行檢查 , 編譯的階段 , 而run time則是指程式進行運作的phase.
Polymorphism 在運作時 , 也有分run time與compile time ,