想请教一个 C++ 关于初始化类时定义和声明的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Waihinchan
V2EX    C++

想请教一个 C++ 关于初始化类时定义和声明的问题

  •  
  •   Waihinchan 2020-04-17 18:29:21 +08:00 3079 次点击
    这是一个创建于 2033 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我最近在 openframework 做作品的时候遇到了一个困难,在实例化一个类的时候我发现如果类本身定义了构造器,那我在实例化的时候就必须带构造器。有没有办法我先声明,然后我再在别的函数里面构造呢?

    比如说有这么一个类是这么写的:

    class dot { int speed; dot(int i ) } dot::dot(int i ){ sped = i; } 

    然后比如我要实例化它的时候我发现是需要这么写:

    dot dottest(1); 

    否则好像他是没有办法被初始化的? 但是实际问题是,我在 OF 中它是带 setup 和 draw 函数的。 通常情况下如果我想在 setup 中初始化这个类,然后在 draw 函数中循环运行它的话,我必须要把这个类声明在函数外,但我只想在 setup 中构造它,但目前好像我测试了好几次都不行。 有没有办法先声明然后在定义呢? 我查到了关于<extern>的用法,但是它似乎并不是我想要的。因为我本质上还是在一个 cpp 文件里面去声明它。 还有一种情况是如果在 h 文件定义,在 cpp 文件中也可以调用。但只要是构造器带了参数的,在 h 文件中好像就没有办法很好的定义这个对象。 我之所以有这个疑问是因为,在 processing 中,实例化可以这么写:

    FlowField flowfield; void setup() { flowfield = new FlowField(10); } void draw(){ } 

    我查了一下 C++和 java 的 new 的区别,还有声明和定义的区别,本来用的好好的现在越看越懵。所以如果我想模仿上面 processing 这么的写法,我在 C++中应该如何实现呢? 我知道 C++是有默认构造器的,我以前的写法是自己额外写一个函数去初始化类里面的变量。但是前段时间突发奇想想用一下构造器,结果就傻眼了。关于 C++声明和定义的一些相关的介绍我也看了,但还是处于似懂非懂的状态。求大家指条明路。。

    11 条回复    2020-04-26 10:22:24 +08:00
    InkStone
        1
    InkStone  
       2020-04-17 18:32:25 +08:00
    如果是你自己写的类,你可以写一个轻量级的构造器,加上一个包含了真正初始化逻辑的 init 函数。

    如果是别人写的类,考虑下用一个单例类来包装一下这个对象,来实现你想要的延迟加载。
    Waihinchan
        2
    Waihinchan  
    OP
       2020-04-17 18:38:30 +08:00
    @InkStone 嗯嗯 感谢 其实总体我也明白有很多方法可以规避这个问题。其实是我有点钻牛角尖了,因为我本来不是很系统地学习过 C++,感觉学到后面深入的有一些概念就开始模糊和混淆了。
    另外想问一下:您回复的关于这个轻量级的构造器,我是否可以理解为真正发挥作用的还是自己写的 init 函数,而他构造器本身可以直接缺省?
    stackexplode
        3
    stackexplode  
       2020-04-17 18:40:11 +08:00
    class A {
    public:
    A() = default;
    Initialize(int speed) {speed_ = speed;}
    private:
    int speed_;
    }

    A a;
    a.Initialize(1);

    =======================

    class B {
    public:
    B(int speed) : speed_(speed) {}
    private:
    int speed_;
    }

    std::unique_ptr<B> b;

    b = std::make_unique<B>(1);
    Waihinchan
        4
    Waihinchan  
    OP
       2020-04-17 18:41:49 +08:00   1
    @stackexplode 感谢回复! classA 的我看懂了 classB 的我再消化消化 非常感谢。
    stackexplode
        5
    stackexplode  
       2020-04-17 18:42:56 +08:00
    @Waihinchan B* b; b = new B(1); 也可以,一样
    ysc3839
        6
    ysc3839  
       2020-04-18 05:36:00 +08:00 via Android
    用指针吧,setup 里面 new 然后返回到外面,再传递进 draw 。
    或者用 std::optional 也行,相比之下更安全 (不会有忘记 delete 的问题),不需要动态分配内存。
    https://zh.cppreference.com/w/cpp/utility/optional
    Wirbelwind
        7
    Wirbelwind  
       2020-04-18 06:45:56 +08:00
    有用户定义的构造函数时,编译器不会生成其他构造函数。
    没有用户定义的构造函数时,编译器看 class 里面成员变量类型来判断是否需要生成构造函数,因为普通内置类型如 char,int,long long 可以通过直接拷贝值来完成。如果有定义了构造函数的 class,比如说 std::string,会生成一个构造函数,这个构造函数里面会递归调用 std::string 的构造函数。

    差不多是这样。

    dot()=default;

    dot(int i )前面加一句这个就可以了。
    Wirbelwind
        8
    Wirbelwind  
       2020-04-18 06:51:07 +08:00
    还有一种写法是使用 placement new 来申请一定的内存,但是不进行构造。

    在需要这块内存的时候调用相关构造函数,不需要的时候调用析构函数。

    不过,不需要这块内存(不再使用 new 的对象)都是需要 delete 调用的
    Waihinchan
        9
    Waihinchan  
    OP
       2020-04-18 07:24:21 +08:00 via Android
    @ysc3839 感谢回复~现在我基本上掌握了指针的用法 其实关于 delete 的问题我也查阅了一下 应该是只要进程结束了内存还是会释放掉的吧?我主要做的是一些展示性的程序 感觉手动释放对于我这个问题并不会是一个很大的阻碍 XD
    codyfeng
        10
    codyfeng  
       2020-04-18 21:53:46 +08:00
    std::unique_ptr 不需要手动释放。其 dtor 会自动 delete 。
    banxi1988
        11
    banxi1988  
       2020-04-26 10:22:24 +08:00
    推荐一下我的总结:
    重学 C++ (1) 对象创建的这件小事 https://mp.weixin.qq.com/s/b0PeGYpb-iKfbI_N7QnQqg
    重学 C++ (2) 从内存分配角度看对象的创建 https://mp.weixin.qq.com/s/IjMGi2cpQzucYdOufpVpBg
    重学 C++ (04) 对 new/delete 说不! https://mp.weixin.qq.com/s/LrYagIpuvJyDqUQRq1xzNg
    重学 C++(05) 手写 unique_ptr https://mp.weixin.qq.com/s/Ni8YUlyIyhHzoqvX2hvruw
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3419 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 04:41 PVG 12:41 LAX 20:41 JFK 23:41
    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