【问题标题】:C++ choose template type of class member in constructorC++在构造函数中选择类成员的模板类型
【发布时间】:2017-11-03 05:40:46
【问题描述】:

我正在尝试在非模板类中定义模板类,您可能会在下面看到我实际尝试执行的代码(由于显而易见的原因,它无法编译)。主要问题是我如何才能意识到使用 C++11(首选)或 C++14?

  1. 实际上,我已经使用std::variant 或 BOOST 库中的相同函数获得了解决方案,但我需要知道另一种解决方法。

  2. 我发现了类似的 question,Anne Quinn 的回答听起来很有价值(他建议为我需要的每种类型声明子类),但是如何在代码中应用它呢?

代码:

#include <vector>
#include <cstdint>

enum Type {
    INT16,
    UINT32
};

template<typename T>
class Buffer {
public:
    Buffer(uint32_t paramSize) {
        buffer.resize(paramSize);
    }

private:
    std::vector<T> buffer;
};

class Foo {
public:
    Foo(Type paramType, uint32_t paramSize) {
        switch(paramType) {
        case UINT32:
            buffer = Buffer<uint32_t>(paramSize);
            break;
        case INT16:
            buffer = Buffer<int16_t>(paramSize);
            break;
        }
    }

private:
    Buffer buffer;
};

int main() {
    Foo var(INT16, 30);

    return 0;
}

UPD1: @user2308211 的回答似乎可行,但我遇到了两个问题。如果我正在复制对象 Foo 并且原始对象由于某种原因被破坏(例如超出范围),则复制将保持指向无处的指针。第二个是如何通过 Foo 类检索我的缓冲区。

UPD2: shared_ptr 解决了复制的问题,但是复制将存储相同的对象,如果您想单独修改它们,请使用复制构造函数,如答案所示。至于访问原始缓冲区,void指针允许您检索指向向量的指针,然后您应该将其静态转换为您的类型。

谢谢!

【问题讨论】:

  • 您可以使您的Buffer 多态并从单个非模板库继承它。
  • @HolyBlackCat 我需要看一些实现的例子,对我来说听起来很新鲜

标签: c++ class c++11 templates dynamictype


【解决方案1】:

有一个基类,其中包含Buffer 所需的所有函数作为纯虚拟。

#include <vector>
#include <cstdint>

enum Type {
    INT16,
    UINT32
};

class BufferBase {
public:
    virtual void someFn()=0;
    virtual ~BufferBase() {}
};

template<typename T>
class Buffer:public BufferBase {
public:
    Buffer(uint32_t paramSize) {
        buffer.resize(paramSize);
    }

    void someFn() override {
      //functionality.
    }
    ~Buffer() {}

private:
    std::vector<T> buffer;
};

class Foo {
public:
    Foo(Type paramType, uint32_t paramSize) {
        this->bufferType = paramType;
        switch(paramType) {
        case UINT32:
            buffer = new Buffer<uint32_t>(paramSize);
            break;
        case INT16:
            buffer = new Buffer<int16_t>(paramSize);
            break;
        }
    }
    ~Foo() {
        delete this->buffer;
    }
    Foo &operator=(const Foo &other) {
        this->bufferType = other.bufferType;
        switch(bufferType) {
        case UINT32:
            buffer = new Buffer<uint32_t>(*static_cast<Buffer<uint32_t>*>(other.buffer));
            break;
        case INT16:
            buffer = new Buffer<int16_t>(*static_cast<Buffer<int16_t>*>(other.buffer));
            break;
        }
        return *this;
    }
    Foo(const Foo &other) {
        *this=other;
    }

private:
    BufferBase *buffer;
    Type bufferType;
};

int main() {
    Foo var1(INT16, 30), var2(UINT32, 25);
    var1 = var2;

    return 0;
}

编辑:我已经用复制构造函数更新了答案。

【讨论】:

  • 感谢您的回答。这里只有一个问题,如果我正在复制对象 Foo 并删除原始对象,则副本将获得指向无处的指针。
  • 您需要更新 Foo 的复制构造函数才能执行深层复制。这会给你正确的行为。如果你想进一步优化,你可以考虑创建一个移动构造函数,它会重新分配指针。
  • 只有当您完全确定自己在做什么时,才可以使用共享指针。我的理解是,您可能想要复制 Foo 对象并独立修改它们。共享指针不会给你这个。
  • 嗯,是的,我确实想要缓冲区应该如何工作,它应该是线程安全的并且可以通过副本获得,所以基本上应该是同一个对象。最后一个问题是我无法从 Foo 类中获取缓冲区数据,我只能通过公共指针来做到这一点。
猜你喜欢
  • 2013-05-07
  • 1970-01-01
  • 2017-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-11
  • 1970-01-01
相关资源
最近更新 更多