Jacob Leach Jacob Leach - 3 months ago 10
C++ Question

Seemingly unable to pass class as constructor argument

I'm trying to pass a class as an argument in another class's constructor, seems whatever I do though I come up with 2 errors:

'ice_type': no appropriate default constructor available


no default constructor exists for class "ice_type"



lexer.h


#pragma once
#include <string>
#include "token.h"

class ice_token;

class ice_lexer {
public:
std::string source;
unsigned int line;
unsigned int pos;
unsigned int ptr;
ice_lexer(std::string file_name);
ice_token lexer_next();
};



token.h


#pragma once
#include <string>
#include "lexer.h"

class ice_lexer;

enum ice_type_enum {
ICE_NONE,
ICE_EOF,
ICE_MODULE,
ICE_IDENT,
ICE_FLT,
ICE_NUM,
ICE_STR,
// SYMBOLS
ICE_RPARA,
ICE_LPARA,
ICE_RBRAC,
ICE_LBRAC,
ICE_RCURL,
ICE_LCURL,
ICE_PERIOD,
ICE_COLON,
ICE_SEMIC,
ICE_COMMA,
// COMPARISON
ICE_EQLTO,
ICE_NOTEQL,
ICE_GRT,
ICE_GRTEQL,
ICE_LES,
ICE_LESEQL,
// ASSIGNMENT
ICE_EQL,
ICE_ADDEQL,
ICE_SUBEQL,
ICE_MULEQL,
ICE_DIVEQL,
ICE_CAREQL,
// URNARY
ICE_URNARYNOT,
ICE_URNARYSUB,
// BINARY
ICE_ADD,
ICE_SUB,
ICE_MUL,
ICE_DIV,
ICE_MOD,
ICE_CAR,
ICE_CAT,
// TERNARY
ICE_TERNARY,
// KEYWORDS
ICE_IMPORT,
ICE_AS,
ICE_WHILE,
ICE_FOR,
ICE_BREAK,
ICE_IF,
ICE_RETURN,
ICE_TRUE,
ICE_FALSE,
// TYPES
ICE_TYPEDEF,
ICE_CLASS,
ICE_ENUM,
ICE_INT,
ICE_FLOAT,
ICE_STRING,
ICE_BOOLEAN,
ICE_VOID,
ICE_STRUCT
};

static const std::string ice_type_enum_strings[] = {
// ABSTRACT
"no type",
"end of file",
"module",
"identifier",
"floating",
"number",
"string",
// SYMBOLS
"left para",
"right para",
"left brac",
"right brac",
"left curl",
"right curl",
"period",
"colon",
"semi",
"comma",
// COMPARISON
"eql to",
"not eql",
"grt",
"grt eql",
"les",
"les eql",
// ASSIGNMENT
"eql",
"add eql",
"sub eql",
"mul eql",
"div eql",
"car eql",
// URNARY
"urnarynot",
"urnarysub",
// BINARY
"add",
"sub",
"mul",
"div",
"mod",
"car",
"cat",
// TERNARY
"ternary",
// KEYWORDS
"import",
"as",
"while",
"for",
"break",
"if",
"return",
"true",
"false",
// TYPES
"typedef",
"class",
"enum",
"int",
"float",
"string",
"bool",
"void",
"struct"
};

class ice_type {
public:
std::string string;
ice_type_enum type;
ice_type(ice_type_enum t);
};

class ice_token {
public:
ice_type type;
size_t line;
size_t pos;

union {
std::string str;
double flt;
size_t num;
};

ice_token::ice_token(ice_lexer *const lexer, ice_type_enum t);
};


The error occurs on the file below at ice_token's constructor, visual studio intellisense is putting the squigglies on the opening curly bracket of the constructor.

#include <string>
#include "token.h"
#include "lexer.h"

ice_type::ice_type(ice_type_enum t) {
string = ice_type_enum_strings[t];
type = t;
}

ice_token::ice_token(ice_lexer *const lexer, ice_type_enum t) {
type = ice_type(t);
line = lexer->line;
pos = lexer->pos;
num = 0;
}


Thanks, help is appreciated!

Answer

The problem is quite simple. You initialize your member variables in a Java-esque manner. But C++ doesn't work that way. A constructor always calls the constrcutors of all base classes and members before its own body is even reached. You can specify parameters to the various c'tors using member initializer lists.

However your constructor doesn't, so the compiler attempts to call the default constructor first (a no parameter one). So a fix would be:

ice_token::ice_token(ice_lexer *const lexer, ice_type_enum t):
  type(t), line(lexer->line), pos(lexer->pos), num(0)
{}