OOP Lec6: Composition & Namespace

Composition

Each object has its own memory consists of other objects. -- Alan Kay

组合是在一个类中使用其他的类的对象作为成员。

包含的两种类型:

  1. 完全包含(Fully)
  2. 引用包含(By reference)(这种方法允许共享对象)

语法

class Person{};
class Currency{};
class SavingsAccount{
public:
    SavingsAccount(const char* name, const char* address, int cents);
    ~SavingsAccount();
    void print();
private:
    Person m_saver;
    Currency m_balance;
};

构造函数

SavingsAccount::SavingsAccount(const char* name, const char* address, int cents):
    m_saver(name, address), m_balance(0, cents){}

注意事项:

  1. 可以使用子对象的构造列表
  2. 如果不使用列表初始化,子对象的默认构造函数会被调用

子对象在本体中的属性

Private vs. Public

通常来说,子对象应该设为 private。这是因为我们希望子对象只与本体对象交互,而对象与外界的交互应该由本体的接口完成。

但如果你想将子对象作为本体与外界的一个交互平台,那么应该设为 public

Fully vs. By Reference

如果子对象完全包含于本体,那么本体中会为子对象保留空间,同时子对象的构造函数、析构函数会自动调用。

如果本体只包含子对象的引用,那么本体中只保留了指针的空间,子对象的构造和析构需要在类的外部手动完成。

应当使用引用包含的情况:

  1. 逻辑上子对象应该在外部(监视器等)

  2. 子对象的大小在开始时不确定

  3. 子对象的空间应该在运行时被分配,或者被链接过来

其他的编程语言只使用 By reference。

举例:Clock Display

我们想实现一个表示时间的类,有时、分、秒。可以分别用对象表示。

时间流逝,可以让秒动一下,如果到了秒的上界(60),就让分动一下。

numberdisplay.h 部分内容:

class NumberDisplay{
public:
    NumberDisplay(int limit, int value = 0);// create a number display with a given up-limit
    void setValue(int value);// set the value
    int getValue();// get the value
    std::string toString();// get a string description of the value, with leading 0 for value less than 10
    bool dida();// increase the value by one, turn over to zero if the value reaches the limit, returns true if the value turned to zero
private:
    int value, limit;
};

clock.h 部分内容:

class Clock{
public:
    Clock(int hour, int minute, int second);// create a clock with given time
    std::string toString();// get a string description of "hh:mm:ss"
    void dida();// run a second
private:
    NumberDisplay hh, mm, ss;
};

具体实现,请读者自行补充(可能是一次 Lab)。

Namespace

需求

通过作用域避免名字的冲突。

之前使用的方法:

class Marbles{
    enum Colors{Blue, Red, Green};
    //...
};
class Candy{
    enum Colors{Blue, Red, Green};
    //...
};

现在可以使用 namespace 语句声明命名空间,完成此类任务。

只推荐在仅需要命名封装的时候使用 namespace

语法

namespace sp1{
    void f();
    void g();
}
namespace sp2{
    void f();
    void g();
}// No terminating end colon!
namespace alias = sp1;
void f();
void g();
int main(){
    sp1::f();
    sp2::f();
    ::f();
    f();// the same as ::f()
    alias::f();// the same as sp1::f()
    return 0;
}

通过 using 语句可以使我们包含一个命名空间内的内容,去掉 ::

using std::cin;
using namespace std;

显然,不能 using 两个同名的对象或函数,否则会使编译器连接失败。

命名空间的作用域就像类一样,是全局的。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇