vindo de um background principalmente python, eu tenho um pouco de dificuldade em trabalhar com tipos em C ++.
Estou tentando inicializar uma variável de classe por meio de um dos vários construtores sobrecarregados que usam tipos diferentes como parâmetros. Eu li que o uso da auto
palavra - chave pode ser usado para declaração automática de uma variável, no entanto, no meu caso, não será inicializado até que um construtor seja escolhido. No entanto, o compilador não está satisfeito por não inicializar value
.
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;
}
};
Em python, isso pode se parecer com:
class Token():
def __init__(self, value):
self.value = value
def printValue(self):
print("The token value is: %s" % self.value)
Qual é a maneira correta de usar a auto
palavra - chave nesse cenário? Devo usar uma abordagem completamente diferente?
auto
para os alunos? Pergunta relevante, mas desatualizada: É possível ter uma variável de membro “auto”?Respostas:
Não existe "variável de tipo desconhecido" em C ++.
variáveis deduzidas automaticamente têm um tipo deduzido do inicializador. Se não houver inicializador, não será possível usar automático. auto não pode ser usado para uma variável de membro não estático. Uma instância de uma classe não pode ter membros de tipo diferente de outra instância.
Não há como usar a palavra-chave automática neste cenário.
Provavelmente. Parece que você está tentando implementar um
std::variant
. Se você precisar de uma variável para armazenar um número X de tipos, é isso que você deve usar.No entanto, você pode estar tentando emular a digitação dinâmica em C ++. Embora possa ser familiar para você devido à experiência com o Python, em muitos casos essa não é a abordagem ideal. Por exemplo, neste programa de exemplo específico, tudo o que você faz com a variável membro é imprimi-lo. Portanto, seria mais simples armazenar uma string em cada caso. Outras abordagens são o polimorfismo estático, como mostrado pelo polimorfismo dinâmico no estilo Rhathin ou OOP, como mostrado pelo Fire Lancer.
fonte
union
é um mecanismo de baixo nível propenso a erros.variant
provavelmente o usa internamente e torna seu uso mais seguro.variant
faz usounion
. A alternativa, usando memória bruta e posicionamento novo, não pode ser usada em umconstexpr
construtor.C ++ é uma linguagem de tipo estaticamente , o que significa que todos os tipos de variáveis são determinados antes do tempo de execução. Portanto,
auto
palavra-chave não é algo comovar
palavra-chave em javascript, que é uma linguagem de tipo dinâmico.auto
A palavra-chave é comumente usada para especificar tipos desnecessariamente complexos.O que você está procurando pode ser feito usando a classe de modelo C ++, o que permite criar várias versões da classe que usa tipos diferentes.
Esse código pode ser a resposta que você está procurando.
Esse código seria compilado se algumas condições fossem atendidas, como a função
operator<<
deve ser definida para std :: ostream & e tipo T.fonte
Uma abordagem diferente da que outros propuseram é usar modelos. Aqui está um exemplo:
Então você pode usar sua classe assim:
fonte
Você pode usar o
std::variant
tipo O código abaixo mostra uma maneira (mas é um pouco desajeitado, devo admitir):Seria muito melhor se o
std::get<0>(value)
poderia ser escrito comostd::get<value.index()>(value)
, mas, infelizmente, o "x" in<x>
deve ser uma expressão constante em tempo de compilação.fonte
std::visit
vez deswitch
.auto
deve ser dedutível para um tipo específico, não fornece digitação dinâmica em tempo de execução.Se, no momento da declaração,
Token
você souber todos os tipos possíveis, poderá usarstd::variant<Type1, Type2, Type3>
etc. Isso é semelhante a ter um "tipo enum" e uma "união". Isso garante que os construtores e destruidores adequados sejam chamados.Uma alternativa poderia ser criar um
Token
subtipo diferente para cada caso (possivelmente usando modelos) com métodos virtuais adequados.fonte
A solução abaixo é semelhante em espírito à da resposta de Fire Lancer. A principal diferença é que segue o comentário possivelmente usando modelos e, assim, elimina a necessidade de criar instâncias derivadas explicitamente da interface.
Token
não é ela mesma a classe de interface. Em vez disso, define a interface como uma classe interna e uma classe de modelo interna para automatizar a definição das classes derivadas.Sua definição parece excessivamente complexa. No entanto,
Token::Base
define a interface eToken::Impl<>
deriva da interface. Essas classes internas estão totalmente ocultas para o usuário deToken
. O uso seria semelhante a:Além disso, a solução abaixo ilustra como alguém pode implementar um operador de conversão para atribuir uma
Token
instância a uma variável regular. Dependedynamic_cast
e lançará uma exceção se o elenco for inválido.A definição de
Token
está abaixo.Experimente online!
fonte