Reusing the implementation
◆ Composition: construct new object with existing objects
◆ It is relationship of "has-a"
Composition
◆ Objects can be used to build up other objects
◆ Ways of inclusion
— Fully
— By reference
◆ Inclusion by reference allows sharing
◆ For example, an Employee has a
— Name
— Address
— Health Plan
— Salary History
★ Collection of Raise objects
— Supervisor
★ Another Employee object!
class Employee { private: int num; Employee* supervisor; };Example
#include <iostream> using namespace std; class Person { private: char* name; char* address; public: Person(const char* name, const char* address); ~Person(); void print(); }; class Currency { private: int cents; public: Currency(int, int cents); ~Currency(); void print(); }; class SavingsAccount //创建SavingsAccount的对象时里面会创建两个对象 { public: SavingsAccount(const char* name, const char* address, int cents); ~SavingsAccount(); void print(); private: Person m_saver; Currency m_balance; }; Person::Person(const char* name, const char* address):name((char*)name),address((char*)address) { } Currency::Currency(int a, int cents) : cents(cents) { } SavingsAccount::SavingsAccount(const char* name, const char* address, int cents) : m_saver(name, address), m_balance(0, cents) { } void Person::print() { } void Currency::print() { } void SavingsAccount::print() { m_saver.print(); m_balance.print(); } Person::~Person() { } Currency::~Currency() { } SavingsAccount::~SavingsAccount() { } int main(int argc, const char* argv[]) { SavingsAccount myaccount; return 0; }Embedded objects
◆ All embedded objects are initialized
— The default constructor is called if
★ you don't supply the arguments, and there is a default constructor( or one can be built)
◆ Constructors can have initialization list
— any number of objects separated by commas
— is optional
— Provide arguments to sub-constructors
◆ Syntax:
name(args) [':' init-list] '{'Question
◆ If we wrote the constructor as( assuming we have the set accessors for the subobjects):
SavingAccount::SavingAccount(const char* name, const char* address, int cents) { m_saver.set_name(name); m_saver.set_address(address); m_balance.set_cents(cents); }◆ Default constructors would be called
Public vs. Private
◆ It is common to make embedded objects private:
— they are part of the underlying implementation
— the new class only has part of the public interface of the old class
◆ Can embed as a public object if you want to have the entire public interface of the subobject available in the new object:
class Person { public: set_name(const char*); }; class Currency { }; class SavingsAccount { public: Person m_saver; Currency m_balance; }; int main(int argc, const char* argv[]) { SavingsAccount account; account.m_saver.set_name("Fred"); //这样,从外部就可以访问Person内的成员函数 return 0; }