模板类之间的友元关系实现Blob和BlobPtr

16.12编写你自己版本的Blob和BlobPtr模板,包含书中未定义的多个const成员。

Blob.h(注意,成员函数的声明和定义要放在一个头文件中)

/*记住,模板的头文件中通常既包括声明也包括定义。函数模板和类模板成员函数的定义通常放在头文件中,不能分开放。。。。谨记*/
#ifndef BLOB_H
#define BLOB_H
#include<iostream>
#include<vector>
#include<string>
#include<memory>
#include<initializer_list>
using namespace std;
template <typename> class BlobPtr;
template <typename> class Blob;
template <typename T>
bool operator==(const Blob<T>&,const Blob<T>&);
template <typename T>
class Blob
{
friend class BlobPtr<T>;
friend bool operator==<T>
    (const Blob<T>&,const Blob<T>&);
public:
    typedef T value_type;
    typedef typename vector<T>::size_type size_type;
    Blob();
    Blob(initializer_list<T> il);
    BlobPtr<T> begin() { return *this;}
    BlobPtr<T> end() { auto ret=BlobPtr<T>(*this,this->size()); return ret;}
    size_type size() const { return data->size();}
    bool empty() const { return data->empty();}
    void push_back(const T &t) { data->push_back(t);}
    void push_back(T &&t) { data->push_back(std::move(t));}
    void pop_back();
    T& front();
    T& back();
    const T& front() const;
    const T& back() const;
    T& operator[](size_type i);
    const T& operator[](size_type i) const;
private:
    shared_ptr<vector<T>> data;
    void check(size_type i,const string &msg) const;
};
template <typename T>
Blob<T>::Blob():
              data(std::make_shared<std::vector<T>>()) { }

template<typename T>
Blob<T>::Blob(initializer_list<T> il):data(make_shared<vector<T>>(il)) {}

template<typename T>
void Blob<T>::check(size_type i,const string &msg) const
{
    if(i>=data->size())
        throw out_of_range(msg);
}

template<typename T>
void Blob<T>::pop_back()
{
    check(0,"pop_back");
    data->pop_back();
}

template <typename T>
T& Blob<T>::front()
{
    check(0,"front");
    return data->front();
}

template<typename T>
T& Blob<T>::back()
{
    check(0,"back");
    return data->back();
}

template<typename T>
const T& Blob<T>::front() const
{
    check(0,"front");
    return data->front();
}

template<typename T>
const T& Blob<T>::back() const
{
    check(0,"back");
    return data->back();
}
template<typename T>
T& Blob<T>::operator[](size_type i)
{
    check(i,"out_of_range");
    return (*data)[i];
}

template<typename T>
const T& Blob<T>::operator[](size_type i) const
{
    check(i,"out_of_range");
    return (*data)[i];
}
template <typename T>
bool operator==(const Blob<T> &lhs,const Blob<T> &rhs)
{
    if(rhs.size()!=lhs.size())
        return false;
    for(size_t i=0;i!=lhs.size();+i)
        if(lhs[i]!=rhs[i])
            return false;
    return true;
}

template <typename T>
ostream operator<<(ostream &os,const Blob<T> &a)
{
    os<<"<";
    for(size_t i=0;i!=a.size();++i)
        os<<a[i]<<" ";
    os<<">";
    return os;
}
template <typename T>
bool operator==(const BlobPtr<T>&,const BlobPtr<T>&);
template <typename T> class BlobPtr
{
friend bool operator==<T>
    (const BlobPtr<T>&,const BlobPtr<T>&);
public:
    BlobPtr():curr(0){}
    BlobPtr(Blob<T> &a,size_t sz=0):wptr(a.data),curr(sz){}
    T& operator*() const
    {
        auto p=check(curr,"dereference past end");
        return (*p)[curr];
    }
    BlobPtr& operator++();
    BlobPtr& operator--();
    BlobPtr& operator++(int);
    BlobPtr& operator--(int);
private:
    shared_ptr<vector<T>> check(size_t,const string &) const;
    weak_ptr<vector<T>> wptr;
    size_t curr;
};
template <typename T>
shared_ptr<vector<T>> BlobPtr<T>::check(size_t i,const string &msg) const
{
    auto ret=wptr.lock();
    if(!ret)
        throw runtime_error("unbind BlobPtr");
    if(i>=ret->size())
        throw out_of_range(msg);
    return ret;
}

template <typename T>
BlobPtr<T>& BlobPtr<T>::operator++()
{
    check(curr,"++");
    ++curr;
    return *this;
}
template <typename T>
BlobPtr<T>& BlobPtr<T>::operator--()
{
    --curr;
    check(curr,"--");
    return *this;
}
template <typename T>
BlobPtr<T>& BlobPtr<T>::operator++(int)
{
    auto ret=*this;
    ++*this;
    return ret;
}

template <typename T>
BlobPtr<T>& BlobPtr<T>::operator--(int)
{
    auto ret=*this;
    --*this;
    return ret;
}

template <typename T>
bool operator==(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{
    return (lhs.wptr.lock().get()==rhs.wptr.lock().get())&&lhs.curr==rhs.curr;
}

template <typename T>
bool operator!=(const BlobPtr<T> &lhs,const BlobPtr<T> &rhs)
{
    return !(rhs==lhs);
}

#endif // BLOB_H

main.cpp

#include "Blob.h"

int main()
{
    Blob<string> b1; // empty Blob
    cout << b1.size() << endl;
    {  // new scope
        Blob<string> b2 = {"a", "an", "the"};
        b1 = b2;  // b1 and b2 share the same elements
        b2.push_back("about");
        cout << b1.size() << " " << b2.size() << endl;
    } // b2 is destroyed, but the elements it points to must not be destroyed
    cout << b1.size() << endl;
    for(auto p = b1.begin(); p != b1.end(); ++p)
        cout << *p << endl;

    return 0;
}

16.14 编写Screen类模板,用非类型参数定义Screen的高和宽。

16.15为你的Screen模板实现输入和输出运算符。Screen类需要哪些友元来令输入和输出运算符正确工作。

#include<iostream>
#include <string>
using namespace std;
//模板非类型参数,友元一定要前置声明
template <unsigned H,unsigned W>
class Screen;
template <unsigned H,unsigned W>
ostream& operator<<(ostream &os,const Screen<H,W> &s);
template <unsigned H,unsigned W>
istream& operator>>(istream &is,Screen<H,W> &s);
template <unsigned H,unsigned W>
class Screen
{
friend ostream& operator<< <H,W> (ostream &os,const Screen<H,W> &s);
friend istream& operator>> <H,W> (istream &is,Screen<H,W> &s);
public:
    typedef string::size_type pos;
    Screen()=default;
    Screen(pos ht,pos wd,char c):height(ht),width(wd),contents(ht*wd,c){}
    char get() const
    {
        return contents[cursor];
    }
    inline char get(pos ht,pos wd) const;
    Screen &move(pos r,pos c);
private:
    pos cursor=0;
    pos height=H;
    pos width=W;
    string contents;
};

template<unsigned H,unsigned W>
char Screen<H,W>::get(pos ht,pos wd) const
{
    pos row=ht*width;
    return contents[row+wd];
}

template <unsigned H,unsigned W>
Screen<H,W>& Screen<H,W>::move(pos r,pos c)
{
    pos row=r*width;
    cursor=row+c;
    return *this;
}
template <unsigned H,unsigned W>
ostream& operator<<(ostream &os,const Screen<H,W> &s)
{
    os<<s.cursor<<" "<<s.height<<" "<<s.width<<" "<<s.contents[s.cursor]<<endl;
    return os;
}
template <unsigned H,unsigned W>
istream& operator>>(istream &is,Screen<H,W> &s)
{
    is>>s.cursor>>s.height>>s.width>>s.contents;
    return is;
}
int main()
{}

16.16

时间: 2024-11-12 06:00:31

模板类之间的友元关系实现Blob和BlobPtr的相关文章

UML 类与类之间的四大关系的一些图标及代码含义

UML 类与类之间的四大关系的一些图标及代码含义 另一个版本: 关联:连接模型元素及链接实例,用一条实线来表示: 依赖:表示一个元素以某种方式依赖于另一个元素,用一条虚线加箭头来表示: 聚合:表示整体与部分的关系,用一条实线加空心菱形来表示: 组成:表示整体与部分的有一关系,用一条实线加实心菱形来表示: 泛化(继承):表示一般与特殊的关系,用一条实线加空心箭头来表示: 实现:表示类与接口的关系,用一条虚线加空心箭头来表示:类与类之间存在以下关系:(1)泛化(Generalization)(2)关

验证当多个类之间有继承关系时,创建子类对象会导致父类初始化块的执行。

结果:当多个类之间有继承关系时,创建子类对象会导致父类初始化块的执行.

Hibernate中的Entity类之间的继承关系之一MappedSuperclass

在hibernate中,Entity类可以继承Entity类或非Entity类.但是,关系数据库表之间不存在继承的关系.那么在Entity类之间的继承关系,在数据库表中如何表示呢? Hibernate提供了4种兼容JPA的策略,解决Entity类的继承与关系数据库表的对应不匹配问题.这里介绍第一种MappedSuperclass. 在这种策略中,存在如下特征: 只在Entity类之间存在继承关系,其中的父Entity类使用@javax.persistence.MappedSuperclass标注

Python设计模式 - 基础 - 类与类之间的六种关系

在程序中需要把世间万物抽象成相应的类,现实世界中物与物之间的关系和程序中类与类之间的关系相对应,因为世间万物是普遍联系的,所以程序中类与类之间也不是孤立的.在系统分析和框架设计中,根据面向对象机制的三大特性:封装.继承.多态,归纳和扩展出类与类之间六种不同的关系: - 依赖关系Dependency: 在局部变量,方法的形参,或者对静态方法的调用中实现 - 关联关系Association: 在类的成员变量中实现,可以双向也可以单向 - 聚合关系Aggregation: 强关联,整体与部分的关系,但

【未完成】类之间的各种关系

一.依赖关系 假设A类的变化引起了B类的变化,就说明B依赖于A. 在UML图中,用虚线箭头表示类之间的依赖关系. 依赖关系有下面具体三种情况. 1.A类是B类中的局部变量,这时,A的变化能够引起B变化,说明B依赖A. 2.A类是B类方法中的一个参数,A变化同样能引起B变化. 3.A类向B类发送消息,这样A也能使B发生变化,也能说B依赖A. public class Driver { public void drive(Car car){ //类Car是Driver里一个方法的参数,说明Car的变

类之间的依赖关系和组合关系

目录 类之间的依赖关系和组合关系 依赖(关联)关系 组合(聚合)关系 一对多的组合关系 类之间的依赖关系和组合关系 依赖(关联)关系 类之间可以有三种关系: 依赖(关联)关系 组合(聚合)关系 继承(实现)关系 依赖(关联)关系指的是类对象执行某个动作的时候,需要其他类的对象来帮助完成这个操作的情况,其特点为: 将一个类的对象或者类名传到另一个类的方法中使用 此时的关系是最轻的,随时可以更换其他对象 关联关系的示例如下: class Person: def play(self, tools):

UML类图画法及类之间几种关系

文章目录如下: 一.类图画法 二.类之间的几种关系:泛化(Generalization).实现(Realization).关联(Association)(又分一般关联.聚合(Aggregation).组合(Composition)).依赖(Dependency) 一.类图画法 1.  类图的概念 A.显示出类.接口以及它们之间的静态结构和关系 B.用于描述系统的结构化设计 2.  类图的元素 类.接口.协作.关系,我们只简单介绍一下这四种元素. 同其他的图一样,类图也可以包含注解和限制. 类图中

当多个类之间有继承关系时,创建子类对象会导致父类初始化块的执行。

源代码 public class inherit { public static void main(String[] args){ first a=new first(); a.show(); } } class second{ String name; { name="zxr"; } } class first extends second{ int age=20; void show() { System.out.println("名字"+name); Sys

eclipse如何查看类之间的引用关系

今天遇到这个问题:mark一点点: 在类名上单击右键.选择Reference->Workingspace快捷克债券Ctrl+Shift+G 版权声明:本文博客原创文章,博客,未经同意,不得转载.