Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过C+中的重载构造函数初始化未知类型的变量+; 来自一个主要的Python背景,我在C++中使用了一些类型的工作。_C++_Constructor_Initialization_Overloading_Auto - Fatal编程技术网

通过C+中的重载构造函数初始化未知类型的变量+; 来自一个主要的Python背景,我在C++中使用了一些类型的工作。

通过C+中的重载构造函数初始化未知类型的变量+; 来自一个主要的Python背景,我在C++中使用了一些类型的工作。,c++,constructor,initialization,overloading,auto,C++,Constructor,Initialization,Overloading,Auto,我试图通过几个重载构造函数之一初始化一个类变量,这些重载构造函数采用不同的类型作为参数。我已经读到,使用auto关键字可以用于变量的自动声明,但是在我的情况下,在选择构造函数之前,它不会被初始化。但是,编译器不喜欢不初始化值 class Token { public: auto value; Token(int ivalue) { value = ivalue; } Token(float fvalue) { value = f

我试图通过几个重载构造函数之一初始化一个类变量,这些重载构造函数采用不同的类型作为参数。我已经读到,使用
auto
关键字可以用于变量的自动声明,但是在我的情况下,在选择构造函数之前,它不会被初始化。但是,编译器不喜欢不初始化

class Token {
public:

    auto value;

    Token(int ivalue) {
        value = ivalue;
    }
    Token(float fvalue) {
        value = fvalue;
    }
    Token(std::string svalue) {
        value = svalue;
    }

    void printValue() {
        std::cout << "The token value is: " << value << std::endl;
    }
};
在这种情况下,使用
auto
关键字的正确方法是什么?我应该使用完全不同的方法吗

通过C中的重载构造函数初始化未知类型的变量++

< C++ >中没有“未知类型变量”之类的东西。 在这种情况下,使用auto关键字的正确方法是什么

自动推导的变量具有从初始化器推导的类型。如果没有初始化器,则不能使用auto。auto不能用于非静态成员变量。类的一个实例不能具有与另一个实例不同类型的成员

在这种情况下,无法使用auto关键字

我应该使用完全不同的方法吗

可能吧。看起来您正在尝试实现一个
std::variant
。如果您需要一个变量来存储X个类型中的一个,那么您应该使用这个变量


但是,您可能试图在C++中模拟动态类型。虽然您可能对Python很熟悉,但在许多情况下,这并不是理想的方法。例如,在这个特定的示例程序中,您对成员变量所做的就是打印它。因此,在每种情况下存储一个字符串会更简单。其他方法如Rhathin所示或Fire Lancer所示的OOP样式。

auto
必须可推断为特定类型,它不提供运行时动态类型

如果在声明
Token
时,您知道可以使用的所有可能类型
std::variant
等。这类似于使用“类型枚举”和“联合”。它确保调用正确的构造函数和析构函数

std::variant<int, std::string> v;
v = "example";
v.index(); // 1, a int would be 0
std::holds_alternative<std::string>(v); // true
std::holds_alternative<int>(v); // false
std::get<std::string>(v); // "example"
std::get<int>(v); // throws std::bad_variant_access

与其他人提出的不同的方法是使用模板。以下是一个例子:

template<class T>
class Token {
public:

    T value;

    Token(T value) :
        value(std::move(value))
    {}

    void printValue() {
        std::cout << "The token value is: " << value << std::endl;
    }
};
模板
类令牌{
公众:
T值;
令牌(T值):
值(标准::移动(值))
{}
void printValue(){

std::cout您可以使用
std::variant
类型。下面的代码显示了一种方法(但我不得不承认,它有点笨拙):

#包括
#包括
类令牌{
公众:
std::变量值;
代币(国际货币){
价值=价值;
}
令牌(浮点值){
价值=价值;
}
标记(标准::字符串值){
值=S值;
}
void printValue(){
开关(value.index()){
案例0:
std::coutC++是一个,意味着所有变量类型都是在运行前确定的。因此,
auto
关键字与javascript中的
var
关键字不同,后者是一种动态类型语言。
auto
关键字通常用于指定不必要的复杂类型

您所寻找的可能是使用C++模板类来完成的,它允许创建不同类型的类的多个版本。

这段代码可能就是您要寻找的答案

template <typename T>
class Token {
private:
    T value;

public:
    Token(const T& ivalue) {
        value = ivalue;
    }

    void printValue() {
        std::cout << "The token value is: " << value << std::endl;
    }
};
模板
类令牌{
私人:
T值;
公众:
代币(const T&ivalue){
价值=价值;
}
void printValue(){

std::cout下面的解决方案在精神上与Fire Lancer的答案中的解决方案类似。它的关键区别在于,它可能使用模板跟随注释,从而消除了显式创建接口派生实例的需要。
Token
本身不是接口类。相反,它将接口定义为内部类类和一个内部模板类来自动定义派生类

它的定义似乎过于复杂。但是,
Token::Base
定义了接口,
Token::Impl
从接口派生。这些内部类对
Token
的用户完全隐藏。用法如下:

class Token():
        def __init__(self, value):
             self.value = value

        def printValue(self):
             print("The token value is: %s" % self.value)
Token s = std::string("hello");
Token i = 7;

std::cout << "The token value is: " << s << '\n';
std::cout << "The token value is: " << i << '\n';
标记的定义如下所示

class Token {

    struct Base {
        virtual ~Base () = default;
        virtual std::ostream & output (std::ostream &os) = 0;
    };

    template <typename T>
    struct Impl : Base {
        T val_;
        Impl (T v) : val_(v) {}
        operator T () { return val_; }
        std::ostream & output (std::ostream &os) { return os << val_; }
    };

    mutable std::unique_ptr<Base> impl_;

public:

    template <typename T>
    Token (T v) : impl_(std::make_unique<Impl<T>>(v)) {}

    template <typename T>
    operator T () const { return dynamic_cast<Impl<T>&>(*impl_); }

    friend auto & operator << (std::ostream &os, const Token &t) {
        return t.impl_->output(os);
    }
};
类令牌{
结构基{
virtual~Base()=默认值;
虚拟std::ostream&output(std::ostream&os)=0;
};
模板
结构Impl:基础{
T瓦卢;
Impl(tv):val_v{}
运算符T(){return val_;}

标准::ostream和输出(标准::ostream和操作系统){返回操作系统,我相信你不能使用<代码> Auto < C++ >类成员,相关但过时的问题:任何不使用模板的原因?Python,在运行时每种操作都确定类型,这需要开销,但是允许变量类型从一个语句变为下一个。o该代码可以编译-float和int具有不同的二进制布局,需要使用不同的汇编指令。如果您希望在运行时具有灵活性,则需要使用联合类型(如variant),该联合类型为每种类型选择包含有效代码的多个分支中的一个,从而增加性能开销。如果您希望保留int和float,则rsion是独立的,模板是你的朋友。最好使用
std::visit
而不是
switch
union
是一种容易出错的低级机制。
variant
可能在内部使用它,使它的使用更安全。@wondra union本身并没有多大用处,因为它无法检查我使用的是哪个成员s当前处于活动状态。与非平凡类(具有自定义析构函数)一起使用(如std::string)也是非常痛苦的。我们需要的是一个带标记的联合。这是datastructu
Token s = std::string("hello");
Token i = 7;

std::cout << "The token value is: " << s << '\n';
std::cout << "The token value is: " << i << '\n';
int j = i; // Allowed
int k = s; // Throws std::bad_cast
class Token {

    struct Base {
        virtual ~Base () = default;
        virtual std::ostream & output (std::ostream &os) = 0;
    };

    template <typename T>
    struct Impl : Base {
        T val_;
        Impl (T v) : val_(v) {}
        operator T () { return val_; }
        std::ostream & output (std::ostream &os) { return os << val_; }
    };

    mutable std::unique_ptr<Base> impl_;

public:

    template <typename T>
    Token (T v) : impl_(std::make_unique<Impl<T>>(v)) {}

    template <typename T>
    operator T () const { return dynamic_cast<Impl<T>&>(*impl_); }

    friend auto & operator << (std::ostream &os, const Token &t) {
        return t.impl_->output(os);
    }
};