Какая-то фигня с виртуальными методами
Всем привет, у меня проблема с компиляцией плюсов. Ниже код и инофрмация об ошибке. Подскажите в чем проблема. Кроме того я нуб в ООП в плюсах, так что если что-то здесь можно переписать идеологически правильнее, скажите и об этом. lex.cpp:
#include "lex.h"
#include <cstring>
#include <list>
struct Ans {
bool fin;
bool err;
int state;
};
static inline Ans newAns(bool f, int s){
Ans a;
a.fin = f;
a.err = 0;
a.state = s;
return a;
}
static inline Ans newErr(){
Ans a;
a.fin = 0;
a.err = 1;
a.state = 0;
return a;
}
#define ISLITS(c) (c >= 'a' && c <= 'z')
#define ISLITB(c) (c >= 'A' && c <= 'Z')
#define ISNUM(c) (c >= '0' && c <= '9')
class Automat {
protected:
virtual Ans nextSymbol(char c);
public:
int len = 0;
int ltype = L_NONE;
int state = 0;
bool fin = 0;
bool err = 0;
std::string text;
bool next(char c){
Ans a = this -> nextSymbol(c);
this -> err = a.err;
if (! this -> err) {
this -> fin = a.fin;
this -> state = a.state;
this -> len ++;
this -> text += c;
}
return ! a.err;
}
};
class Aint : public virtual Automat {
protected:
virtual Ans nextSymbol(char c){
if (c >= '0' && c <= '9')
return newAns(1,0);
return newErr();
}
public:
Aint(){
this -> ltype = L_INT;
}
};
class Areal : public Automat {
protected:
virtual Ans nextSymbol(char c){
switch(this -> state){
case 0:
if (ISNUM(c))
return newAns(0,1);
return newErr();
case 1:
if (ISNUM(c))
return newAns(0,1);
if (c == '.')
return newAns(0,2);
return newErr();
case 2:
if (ISNUM(c))
return newAns(1,2);
return newErr();
default:
return newErr();
}
}
public:
Areal(){
this -> ltype = L_REAL;
}
};
class Astr : public Automat {
protected:
virtual Ans nextSymbol(char c){
switch(this -> state){
case 0:
if (c == '"')
return newAns(0,1);
return newErr();
case 1:
if (c == '"')
return newAns(1,2);
return newAns(0,1);
default:
return newErr();
}
}
public:
Astr(){
this -> ltype = L_STR;
}
};
class Aid : public Automat {
protected:
virtual Ans nextSymbol(char c){
switch(this -> state){
case 0:
if (ISLITS(c) || ISLITB(c) || c == '_')
return newAns(1,1);
return newErr();
case 1:
if (ISLITS(c) || ISLITB(c) || ISNUM(c) || c == '_')
return newAns(1,1);
return newErr();
default:
return newErr();
}
}
public:
Aid(){
this -> ltype = L_ID;
}
};
class Abr : public Automat {
protected:
virtual Ans nextSymbol(char c){
static const char brackets[] = "()[]{};.,";
static int len = 0;
if (len == 0)
len = strlen(brackets);
if (this -> state == 0){
for(int i=0; i<len; ++i)
if(brackets[i] == c)
return newAns(1,1);
}
return newErr();
}
public:
Abr(){
this -> ltype = L_BR;
}
};
class Aop : public Automat {
protected:
virtual Ans nextSymbol(char c){
static const char symbols[] = "+-*/%^&|<>=!\\:#@";
static int len = 0;
if (len == 0)
len = strlen(symbols);
for(int i=0; i<len; ++i){
if(symbols[i] == c)
return newAns(1,1);
}
return newErr();
}
public:
Aop(){
this -> ltype = L_OP;
}
};
using namespace std;
static int skipSpaces(string& str, int pos){
for(;pos < str.length(); ++pos){
char c = str[pos];
if(c != ' ' && c != '\n' && c != '\r' && c != '\t')
return pos;
}
return pos;
}
// is success new str pos will be written to 'spos'
bool lex(string& src, int& spos, string& dst, int& ltype){
// skip space
int pos = skipSpaces(src,spos);
// init alist
list<Automat> alist;
alist.push_back(Aint());
alist.push_back(Areal());
alist.push_back(Astr());
alist.push_back(Aop());
alist.push_back(Abr());
alist.push_back(Aid());
alist.push_back(Aint());
// search
for(;pos < src.length(); pos++){
bool flag = 0;
for(auto& atm : alist)
flag = flag || atm.next(src[pos]);
if(flag)
alist.remove_if([](Automat& atm){return atm.err;});
else
break;
}
// finalize
for(auto& atm : alist){
if(atm.fin){
dst = atm.text;
ltype = atm.ltype;
spos = pos;
return true;
}
}
// if err
return false;
}
#include "lex.h"
#include <iostream>
using namespace std;
int main(){
string text = "\thello world 12 g1 42 \n 12.2 \"dd\" += () 4";
string dst;
int ltype;
int pos = 0;
while(lex(text,pos,dst,ltype)){
cout << "'" << dst << "' " << ltype << "\n";
}
cout << "end\n";
return 0;
}
g++ -c -std=c++0x -O2 lex.cpp
g++ -c -std=c++0x -O2 main.cpp
g++ -std=c++0x -o main -O2 lex.o main.o
Undefined symbols for architecture x86_64:
"typeinfo for Automat", referenced from:
typeinfo for Aid in lex.o
typeinfo for Abr in lex.o
typeinfo for Aop in lex.o
typeinfo for Astr in lex.o
typeinfo for Areal in lex.o
typeinfo for Aint in lex.o
"vtable for Automat", referenced from:
lex(std::string&, int&, std::string&, int&) in lex.o
std::list<Automat, std::allocator<Automat> >::_M_create_node(Automat const&) in lex.o
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)