V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Waihinchan
V2EX  ›  C++

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

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

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

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

    class dot {
    int speed;
    dot(int i )
    }
    dot::dot(int i ){
    speed = 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   ·   我们的愿景   ·   实用小工具   ·   1094 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 18:35 · PVG 02:35 · LAX 11:35 · JFK 14:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.