• C++ 对象组合和继承


    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.

    参考资料:

  • 相关阅读:
    BZOJ 2005 能量采集
    HDU 2841 Visible Trees(莫比乌斯反演)
    hihocoder 1543
    hihocoder 1311
    hdu 6069
    hdu 6058
    hdu 6034
    拓展欧几里得
    poj 3321
    树状数组总结
  • 原文地址:https://www.cnblogs.com/linkworld/p/16263170.html
Copyright © 2020-2023  润新知