`
kmplayer
  • 浏览: 508923 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

条款42:明智地使用private inheritance(私有继承)

阅读更多
1,先搞清楚private inheritance的行为:
(1)如果class之间是私有继承的关系,编译器不会将一个派生类自动转化为基类.
(2)由基类继承而来的所有成员,在派生类中都会变成private.

2,私有继承:只有实现部分被继承,接口部分应略去.
因此,如果你让D私有继承B,那么你是想采用class B内的某些程序代码,而不是因为B和D的对象有任何概念关系存在.

3,回想一下,laying的意义也是这样.那么如何在laying和private inheritance之间取舍呢?
尽可能使用laying,必要时(当protected members或虚函数牵扯进来)才使用private inheritance.

4,模版的坏处:Stack<int>和Stack<double>编译器默认会把代码完全复制一份,造成代码膨胀.

5,可以借助泛型指针避免代码重用的做法.
泛型指针:class存放的是对象指针

6,laying实现泛型指针:
#include <iostream>
using namespace std;

//先定义一个泛型类
class GenericStack
{
public:
    GenericStack();
    void push(void *t);
    void* pop();
    void* top();
    bool empty();
    int size();
    ~GenericStack();
private:
    struct StackNode
    {
        StackNode(void* t, StackNode *nextNode) : data(t),next(nextNode){}
        void* data;
        StackNode* next;
    };
    StackNode* head;
    int cnt;
    GenericStack(const GenericStack&);
    GenericStack& operator=(const GenericStack&);
};


GenericStack::GenericStack() : head(NULL),cnt(0) {}


void GenericStack::push(void* t)
{
    head = new StackNode(t, head);
    cnt++;
}


void* GenericStack::pop()
{
    if (!empty())
    {
        StackNode* tmp = head;
        head = head -> next;
        void* tmpData = tmp -> data;
        delete tmp;
        cnt--;
        return tmpData;
    }
}

void* GenericStack::top()
{
    if (!empty())
        return head -> data;
}

bool GenericStack::empty()
{
    return head == NULL;
}


int GenericStack::size()
{
    return cnt;
}


GenericStack::~GenericStack()
{
    while (head)
    {
        StackNode* tmp = head;
        head = head -> next;
        delete tmp;
    }
}

//laying技术的使用
class IntStack
{
public:
    void push(int *t)
    {
        s.push(t);
    }
    int* pop()
    {
        return static_cast<int*>(s.pop());
    }
    int* top()
    {
        return static_cast<int*>(s.top());
    }
    bool empty()
    {
        return s.empty();
    }
    int size()
    {
        return s.size();
    }
private:
    GenericStack s;
};

class DoubleStack
{
public:
    void push(double *t)
    {
        s.push(t);
    }
    double* pop()
    {
        return static_cast<double*>(s.pop());
    }
    double* top()
    {
        return static_cast<double*>(s.top());
    }
    bool empty()
    {
        return s.empty();
    }
    double size()
    {
        return s.size();
    }
private:
    GenericStack s; //这个成员是核心
};

int main()
{
    IntStack myStack;
    int a = 20, b = 30, c = 40;
    myStack.push(&a);
    myStack.push(&b);
    myStack.push(&c);
    cout << *(myStack.pop()) <<endl;
    cout << myStack.size() <<endl;
    cout << *(myStack.top()) <<endl;

    DoubleStack myStack2;
    double da = 20.11, db = 30.22, dc = 40.33;
    myStack2.push(&da);
    myStack2.push(&db);
    myStack2.push(&dc);
    cout << *(myStack2.pop()) <<endl;
    cout << myStack2.size() <<endl;
    cout << *(myStack2.top()) <<endl;

    return 0;
}

注:上述代码可能存在的隐患:
有人可能会误用GenericStack.

7,借组private inheritance可以给出更好的实现方案.
实例代码:
#include <iostream>
using namespace std;

//先定义一个泛型类
class GenericStack
{
protected:
    GenericStack(); //它的对象无法在外面产生
             //因此可以防止有人直接访问GenericStack
    void push(void *t);
    void* pop();
    void* top();
    bool empty();
    int size();
    ~GenericStack();
private:
    struct StackNode
    {
        StackNode(void* t, StackNode *nextNode) : data(t),next(nextNode){}
        void* data;
        StackNode* next;
    };
    StackNode* head;
    int cnt;
    GenericStack(const GenericStack&);
    GenericStack& operator=(const GenericStack&);
};


GenericStack::GenericStack() : head(NULL),cnt(0) {}


void GenericStack::push(void* t)
{
    head = new StackNode(t, head);
    cnt++;
}


void* GenericStack::pop()
{
    if (!empty())
    {
        StackNode* tmp = head;
        head = head -> next;
        void* tmpData = tmp -> data;
        delete tmp;
        cnt--;
        return tmpData;
    }
}

void* GenericStack::top()
{
    if (!empty())
        return head -> data;
}

bool GenericStack::empty()
{
    return head == NULL;
}


int GenericStack::size()
{
    return cnt;
}


GenericStack::~GenericStack()
{
    while (head)
    {
        StackNode* tmp = head;
        head = head -> next;
        delete tmp;
    }
}

//laying技术的使用
class IntStack : private GenericStack
{
public:
    void push(int *t)
    {
        GenericStack::push(t);
    }
    int* pop()
    {
        return static_cast<int*>(GenericStack::pop());
    }
    int* top()
    {
        return static_cast<int*>(GenericStack::top());
    }
    bool empty()
    {
        return GenericStack::empty();
    }
    int size()
    {
        return GenericStack::size();
    }
};

class DoubleStack : private GenericStack
{
public:
    void push(double *t)
    {
        GenericStack::push(t);
    }
    double* pop()
    {
        return static_cast<double*>(GenericStack::pop());
    }
    double* top()
    {
        return static_cast<double*>(GenericStack::top());
    }
    bool empty()
    {
        return GenericStack::empty();
    }
    double size()
    {
        return GenericStack::size();
    }
};


int main()
{
    IntStack myStack;
    int a = 20, b = 30, c = 40;
    myStack.push(&a);
    myStack.push(&b);
    myStack.push(&c);
    cout << *(myStack.pop()) <<endl;
    cout << myStack.size() <<endl;
    cout << *(myStack.top()) <<endl;

    DoubleStack myStack2;
    double da = 20.11, db = 30.22, dc = 40.33;
    myStack2.push(&da);
    myStack2.push(&db);
    myStack2.push(&dc);
    cout << *(myStack2.pop()) <<endl;
    cout << myStack2.size() <<endl;
    cout << *(myStack2.top()) <<endl;

    return 0;
}
分享到:
评论

相关推荐

    Effective C++(第三版)

    条款39:明智而审慎地使用private继承 use private inheritance judiciously. 条款40:明智而审慎地使用多重继承 use multiple inheritance judiciously. 7. 模板与泛型编程 templates and generic programming ...

    Effective C++ 中文版

    内容简介: 有人说C++程序员可以分成两类,读...条款39:明智而审慎地使用private继承 条款40:明智而审慎地使用private继承 7.模板与泛型编程 8.定制new和delete 9.杂项讨论 A 本书之外 B 新旧版条款对映 索引

    C++公有继承、保护继承和私有继承的区别

    C++提供了三种不同的继承方式,每种方式对基类成员的访问权限有不同的规定,分别是公有继承(public inheritance)、保护继承(protected inheritance)和私有继承(private inheritance)。 1. 公有继承(public ...

    C程序设计教学课件:CHAPTER8INHERITANCE.pptx

    - 私有继承(Private Inheritance):基类的公有和受保护成员在派生类中变为私有的,私有成员仍然仅在基类中可见。 - 受保护继承(Protected Inheritance):基类的公有和受保护成员在派生类中变为受保护的,私有...

    C/C++ 公有继承、保护继承和私有继承的对比详解

    C++ 提供了三种继承方式:公有继承(public inheritance)、保护继承(protected inheritance)和私有继承(private inheritance),每种方式都有不同的访问权限和行为。 1. **公有继承(Public Inheritance)** -...

    详解C++编程中的私有继承和公有继承

    继承分为两种主要类型:私有继承(private inheritance)和公有继承(public inheritance)。这两种继承方式在C++中有着不同的语义和用途。 **私有继承(Private Inheritance)** 在C++中,如果声明一个派生类使用`...

    C++ 中私有继承的作用

    在C++编程语言中,私有继承(private inheritance)是一种特殊的继承方式,它与公有继承(public inheritance)和保护继承(protected inheritance)并列,是面向对象编程中的一个重要概念。私有继承的主要作用和...

    C 程序设计教学课件:CHAPTER 8 INHERITANCE.ppt

    私有继承(Private Inheritance)则表达了一种"Has-A"关系,基类的公有和保护成员在派生类中成为私有的。保护继承(Protected Inheritance)则介于两者之间,保护成员在派生类中保持保护状态。 4. **8.4 Multiple ...

    类的继承练习_inheritance_类的继承练习_C++_pineoce_

    - `private`继承:父类的公有和保护成员在子类中都变为私有,私有成员仍然对子类不可见。 - `protected`继承:与`private`继承类似,但父类的保护成员在子类中仍保持为保护成员。 3. **虚函数与多态**:为了实现...

    C++程序设计教学课件:CHAPTER 8 INHERITANCE.ppt

    - **私有继承**:基类的公有和保护成员在派生类中变为私有,不能直接访问。 - **保护继承**:基类的公有和保护成员在派生类中变为保护,只能在派生类及其子类中访问。 4. **8.4 多重继承** - 一个派生类可以同时...

    c++继承与派生

    * 私有继承(private inheritance):基类的所有成员都不能被派生类访问。 * 保护继承(protected inheritance):基类的保护成员可以被派生类访问。 实验1:继承与派生 实验目的:掌握继承与派生的概念,理解基类...

    c++程序设计 继承与派生实验(二)

    继承方式主要有三种:公有继承(public inheritance)、私有继承(private inheritance)和保护继承(protected inheritance)。在公有继承下,基类的公有和保护成员在派生类中保持相同访问级别;私有继承则使基类的...

    C++远征之继承篇学习笔记之一

    3. **私有继承(Private Inheritance)**: - 在私有继承中,基类的所有公共和受保护成员都会变成派生类中的私有成员。 - 例如:`class A : private B` 表示 `A` 类私有继承 `B` 类。 - **成员访问属性的变化**:...

    C++程序设计课件:第17章 多重继承.ppt

    私有继承(private)使得基类的所有成员对派生类私有,对外部代码不可见,除非在派生类中重新声明为公有或受保护的。 总的来说,多重继承是C++提供的一种强大工具,可以用来构建复杂的类层次结构,但同时也需要处理...

    C++继承与派生类习题.pdf

    - 私有继承(Private Inheritance):基类的公有和保护成员在派生类中变为私有,私有成员不可访问。 4. 二义性问题: - 当派生类从多个基类继承相同的成员或函数时,可能会出现二义性。解决方法通常使用作用域...

    大数据必学Java基础(四十):面向对象三大特性之一继承(Inheritance)

    Java中有四种访问修饰符:private、default(缺省)、protected和public,它们决定了类成员的可见性。 1. private:私有,只能在声明它的类内部访问。 2. default:默认(包私有),在同一包内的类可以访问。 3. ...

    继承与派生

    2. **私有继承(Private Inheritance)**:子类只能访问父类的私有成员和受保护成员,且这些成员在子类中变为私有成员。 3. **受保护继承(Protected Inheritance)**:子类可以访问父类的所有受保护成员,这些成员...

    用派生与继承计算圆面积的代码

    - **私有继承(Private Inheritance)**: 私有继承下,派生类的成员不能直接访问基类的任何成员。如果派生类需要访问基类的成员,则必须通过派生类的成员函数来实现。这种继承关系通常表示为“has-a”关系。 - **...

    子类的四种访问权限

    3. **Private Inheritance (私有继承)**: - 基类中的 `public` 成员在派生类中变为 `private`。 - 基类中的 `protected` 成员在派生类中变为 `private`。 - 基类中的 `private` 成员无法直接在派生类中访问。 ##...

    14 继承(一)(整个继承树映射到一张表)

    让我们更深入地了解这种继承策略: 1. **单表继承(Single Table Inheritance,STI)**:在STI中,所有类的实例都存储在一个表中。每个子类在数据库表中增加一个表示类类型的字段,例如`discriminator_column`。当...

Global site tag (gtag.js) - Google Analytics