[菜鸟求教] 一个 C++ 容器类的疑问 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dlllcs
V2EX    C

[菜鸟求教] 一个 C++ 容器类的疑问

  •  
  •   dlllcs 2015-06-24 21:50:57 +08:00 1731 次点击
    这是一个创建于 3769 天前的主题,其中的信息可能已经有所发展或是发生改变。

    这段时间在学习C++,尝试自己写了一个容器类,开始设想是模拟一个可以放下所有类型的元素的数组(就像vector那样),但是遇到了一点小问题,就像下面代码描述那样,能不能在不更改 Package 类的情况下让 Container 类能实现功能,或者这个思路本身是有问题的,如果思路有问题的话,那该怎样设计才是好的?

    /*  * main.cpp  *  * Created on: Jun 16, 2015  * Author: dlll  */ class Package{ private: int num; public: Package(int num){ this->num = num; } operator int(){ return num; } }; template<class T> class Container{ private: T *contents; public: Container(int size){ contents = new T[size]; } ~Container(){ delete[] contents; } void set(int pos, T content){ contents[pos] = contents; } T get(int pos){ return contents[pos]; } }; int main(int argc, char **argv) { //这样写是可以的 Container<int> intContainer(10); /*  * 这样写是不行的,会报错:  * ../main.cpp:32:13: error: no matching function for call to ‘Package::Package()’  cOntents= new T[size];  * */ Container<Package> packageContainer(10); /*  * 问题: 能不能在不更改 Package 类的情况下让 Container 类能实现功能  */ } 
    第 1 条附言    2015-06-24 22:26:01 +08:00
    package没有默认构造函数这个我有知道,但是测试中 vector 就可以装下没有默认构造函数的package,这是为什么呢?
    6 条回复    2015-06-26 13:33:27 +08:00
    njustyw
        1
    njustyw  
       2015-06-24 22:22:11 +08:00 via Android   1
    package没有默认构造函数
    ini
        2
    ini  
       2015-06-24 22:43:42 +08:00
    vector也要看情况:

    ```
    vector<Package> vec;
    ```

    这种情况是不需要的,因为这时候vector还不会调构造函数。
    ini
        3
    ini  
       2015-06-24 22:48:39 +08:00
    你的 Container 如果要正常工作的话,不要用 new T[size] 来申请内存,这会导致默认构造函数的调用;可以用 malloc 来申请足够的内存,然后再在需要的时候用 placement new 来调用 Package 的构造函数。
    dlllcs
        4
    dlllcs  
    OP
       2015-06-25 13:41:44 +08:00
    @ini 万分感谢哦,经过您的指点,我改成下面这样子完美通过编译和运行,大神看下还有哪里需要改动或者优化不 嘿嘿

    ```c++
    #include <cstdlib>
    #include <iostream>

    class Package{
    private:
    int num;

    public:
    Package() = delete;

    Package(int num){
    std::cout << "create Package " << num << std::endl;
    this->num = num;
    }

    Package(Package& o){
    std::cout << "copy Package " << o.num << std::endl;
    num = o.num;
    }


    virtual ~Package(){
    std::cout << "delete Package " << num << std::endl;
    }


    virtual operator int(){
    return num;
    }
    };

    class Package2 : public Package{
    private:
    int num2;

    public:
    Package2() = delete;

    Package2(int num):Package(-1){
    std::cout << "create Package2 " << num << std::endl;
    this->num2 = num;
    }

    Package2(Package2& o):Package(-1){
    std::cout << "copy Package2 " << o.num2 << std::endl;
    num2 = o.num2;
    }


    virtual ~Package2(){
    std::cout << "delete Package2 " << num2 << std::endl;
    }


    virtual operator int(){
    return num2;
    }
    };

    template<class T>
    class Container{
    private:
    struct contentContainer{
    T content;
    bool isUse;
    };

    contentContainer *contents;
    int size;
    public:
    Container(int size){
    cOntents= (contentContainer *)::malloc(sizeof(contentContainer) * size);
    for(int i = 0; i < size; ++i)
    contents[i].isUse = false;
    this->size = size;
    }

    ~Container(){
    for(int i = 0; i < size; ++i){
    auto &con = contents[i];
    if (con.isUse){
    con.content.~T();
    }
    }
    free(contents);
    }

    void set(int pos, T content){
    auto &con = contents[pos];
    if (con.isUse){
    con.cOntent= content;
    }else{
    new(&con.content) T(content);
    con.isUse = true;
    }
    }

    T& get(int pos){
    return contents[pos].content;
    }
    };

    int main(int argc, char **argv) {
    // 测试 Package 和 Package2 的大小
    std::cout << "sizeof(Package): " << sizeof(Package) << std::endl;
    std::cout << "sizeof(Package2): " << sizeof(Package2) << std::endl << std::endl;

    Container<int> intContainer(10);

    Container<Package> packageContainer(10);
    packageContainer.set(1, Package(100));
    std::cout << packageContainer.get(1) << std::endl;
    }
    ```
    ini
        5
    ini  
       2015-06-25 23:30:35 +08:00   1
    @dlllcs 不要称呼我为“您”或者“大神”,承受不起。。

    你这个作为例子应该差不多了,但从工程角度,应该还有改进的地方:

    1. 只有一个参数的构造函数最好声明为explicit
    2. 不要随便定义转义操作符
    3. 另外,一个类的拷贝构造函数、赋值操作符、析构函数一般是要没有就没有,要有三个都要同时有的(简称rule of three),你这里没有实现完全。

    一家之言,见笑了。
    dlllcs
        6
    dlllcs  
    OP
       2015-06-26 13:33:27 +08:00
    @ini 承你所言,那我就冒昧称呼为你好了,嘿嘿

    你这三个见解确实了结了我对输出结果的疑惑,原来是发生了隐式转换,谢谢啦!以后我会注意的!
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2640 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 03:40 PVG 11:40 LAX 20:40 JFK 23:40
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86