`
kmplayer
  • 浏览: 497110 次
  • 性别: 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;
}
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics