C++ 物件組合和繼承
阿新 • • 發佈:2022-05-12
7. Composition(組合)
- Composition: construct new object with existing objects.
- It is the relationship of "has-a".
- Ways of inclusion:
- Fully
- By reference
- 示例:
class Person { ... }; // 貨幣 class Currency { ... }; // 儲蓄戶口 class SavingsAccount { pubilc: SavingsAccount (const char* name, const char* address, int cents); ~SavingsAccount(); void print(); private: // Fully inclusion Person m_saver; Currency m_balance; }; // Person 和 Currency 初始化 SavingsAccount::SavingsAccount (const char* name, const char* address, int cents) : m_saver(name, address), m_balance(0, cents) {} void SavingsAccount::print() { m_saver.print(); m_balance.print(); }
8. Inheritance(繼承)
- Inheritance: is to take the existing class, clone it, and then make additions and modifications to the clone.
- "Is-a"
- 示例1:訪問父類私有變數
#include <iostream> using namespace std; class A { public: A():i(0) { cout << "A::A()" << endl; } ~A() { cout << "A::~A()" << endl; } void print() { cout << "A::print() ---》 " << i << endl; } void set(int ii) { i = ii; } private: int i; }; // 繼承, 其中 public 必需 class B : public A { public: void f() { set(20); // 直接訪問 i,是會報錯 // 父類私有的成員變數,子類不能直接訪問 i = 30; print(); } }; int main() { B b; b.set(10); b.print(); b.f(); return 0; }
- 示例2:訪問父類 protected 函式
#include <iostream> using namespace std; class A { public: A():i(0) { cout << "A::A()" << endl; } ~A() { cout << "A::~A()" << endl; } void print() { cout << "A::print() ---》 " << i << endl; } protected: void set(int ii) { i = ii; } private: int i; }; // 繼承, 其中 public 必需 class B : public A { public: void f() { set(20); // 直接訪問 i,是會報錯 // 父類私有的成員變數,子類不能直接訪問 // i = 30; print(); } }; int main() { B b; // set 調整為 protected // 子類可以使用,但是,main 函式中不能呼叫 b.set(10); b.print(); b.f(); return 0; }
8.1 子類和父類關係
- 示例1:子類和父類構造順序
#include <iostream>
using namespace std;
class A {
public:
A(int ii):i(ii) {
cout << "A::A()" << endl;
}
~A() {
cout << "A::~A()" << endl;
}
void print() {
cout << "A::print()" << i << endl;
}
void set(int ii) {
i = ii;
}
private:
int i;
};
class B : public A {
public:
B() : A(15) {
cout << "B::B()" << endl;
}
~B() {
cout << "B::~B()" << endl;
}
void f() {
set(20);
print();
}
};
int main()
{
// 父類先初始化,然後才會初始化子類
B b;
b.print();
b.f();
return 0;
}
-
父類和子類構造和析構順序:
-
示例:子類和父類關係
#include <iostream>
class Employee {
public:
Employee(const std::string& name, const std::string& ssn);
const std::string& get_name() const;
void print(std::ostream& out) const;
void print(std::ostream& out, const std::string& msg) const;
protected:
std::string m_name;
std::string m_ssn;
};
Employee::Employee (const std::string& name, const std::string& ssn) :m_name(name), m_ssn(ssn)
{
// initializer list sets up the values!
}
inline const std::string& Employee::get_name() const
{
return m_name;
}
inline void Employee::print(std::ostream& out) const
{
out << m_name << std::endl;
out << m_ssn << std::endl;
}
inline void Employee::print(std::ostream& out, const std::string& msg) const
{
out << msg << std::endl;
print(out);
}
// Manager 類
class Manager : public Employee {
public:
Manager(const std::string& name, const std::string& ssn, const std::string& title);
const std::string title_name() const;
const std::string& get_title() const;
void print(std::ostream& out) const;
private:
std::string m_title;
};
// 子類的構造,直接呼叫父類的建構函式
// 父類的構造過程,也必須放在 initializer list 裡面
Manager::Manager(const std::string& name, const std::string& ssn, const std::string& title = "") :Employee(name, ssn), m_title(title) {
}
inline void Manager::print(std::ostream& out) const {
Employee::print(out); // call the base class print
out << m_title << std::endl;
}
inline const std::string& Manager::get_title() const
{
return m_title;
}
inline const std::string Manager::title_name() const
{
return std::string(m_title + ": " + m_name);
}
int main() {
Employee bob("Bob Jones", "555-44-0000");
Manager bill("Bill Smith", "666-55-1234", "Important Person");
std::string name = bill.get_name();
std::cout << bill.title_name() << "\n" << std::endl;
bill.print(std::cout);
bob.print(std::cout);
bob.print(std::cout, "Employee:");
// Error:
// Manager::print(std::ostream& out) 函式
// 如果父類當中有 overload 函式,子類中出現同名函式時,子類僅保留子類自己的函式
// bill.print(std::cout, "Manager: ");
// 修正:
bill.Employee::print(std::cout, "Manager: ");
}
8.2 Function overloading
- Same functions with different arguments list.
// 示例
void print(char *str, int width); // #1
void print(double d, int width); // #2
void print(long l, int width); // #3
void print(int i, int width); // #4
void print(char *str); // #5
8.2.1 Default arguments
- A default argument is a value given in the declaration that the compiler automatically inserts if you don't provide a value in the function call.
- To define a function with an argument list, defaults must be added from right to left.
8.3 行內函數(inline)
-
the processing time required by a device prior to the execution of a command.
- Push parameters
- Push return address
- Prepare return values
- Pop all pushed
-
An inline function is expanded in place, like a preprocessor macro, so the overhead of the function call is eliminated.
-
示例:
-
a.h
inline void f(int i, int j);
a.cpp
#include "a.h"
#include <iostream>
using namespace std;
inline void f(int i, int j) {
cout << i << " " << j << endl;
}
main.cpp
#include "a.h"
int main()
{
f(10, 10);
return 0;
}
- 編譯異常:
8.3.1 修正
a.h
#include <iostream>
using namespace std;
inline void f(int i, int j) {
cout << i << " " << j << endl;
}
main.cpp
#include "a.h"
int main()
{
f(10, 10);
return 0;
}
8.3.2 Inline functions in header file
- So you can put inline functions' bodies in header file. Then #include it where the function is needed.
- Never be afraid of multi-definition of inline functions, since they have no body at all.
- Definitions of inline functions are just declarations.
8.3.3 行內函數優缺點
- Body of the called function is to be inserted into the caller.
- This may expand the code size.
- but deduces the overhead of calling time.
- So it gains speed at the expenses of space.
- In most cases, it is worth.
- It is much better than macro in C. It checks the types of the parameters.
- Any function you define inside a class declaration is automatically an inline.
參考資料: