antoniogm
asked on
Pulling subclasses of a superclass off of a vector....
My problem is the following:
I define a superclass GapFunction, which is meant to encompass families of probability distributions. Those distributions (gaussian, multinomial, etc.) are subclassed to GapFunction and overload a method or two.
Within MMotif (reproduced below), I define vector<GapFunction> gaps, and then proceed to push on various subclasses of GapFunction on to it. However, when I pull them off the vector and call a method, it defaults to the skeleton methods in GapFunction, rather than the overloaded methods defined in the various subclasses. In Java, I would cast the pulled-off object to the subclass and go from there, but in C++ I am somewhat lost. All help appreciated...Antonio.
class MMotif{
public:
vector<PWM> pwms;
PWM backgr;
vector<Multinomial> gaps;
string MATRIX_DEL;
string FUNC_DEL;
static int const MMotif::maxlength=1000;
static int const MMotif::minlength=1;
/*MMotif(const vector<PWM>& p,
const vector<GapFunction>& g) {
if (p.size() != g.size() + 1) {
std::cout << "PWMs and GapFunctions not numbered accordingly" << std::endl;
} else {
pwms.assign(p.begin(), p.end()); // no need for a loop; use stl
gaps.assign(g.begin(), g.end());
}
}*/
MMotif(char *name){
MATRIX_DEL="M";
FUNC_DEL="F";
Multinomial m1(MMotif.min, MMotif.max);
gaps.push_back(m1);
//cout << "multinomial nullity is " << gaps[0].isFree()<<endl;
ifstream readFile(name, ios::in);
char s[100]; // declares variable to read data from file
vector<string> matrixlines;
bool matricing=false;
bool done=false;
while(!done) {
// cout << readFile.eof() << endl;
readFile.getline(s, 100);
string line(s);
// cout << line << endl;
string buf; // Have a buffer string
stringstream ss(line); //insert the string into a stream
vector<string> tokens; // Create vector to hold our words
while (ss >> buf){
tokens.push_back(buf);
}
//string::size_type firstwhitespace=line.find_
//string type=line.substr(0, firstwhitespace);
//string trunc_line=line.substr(fir
string type=tokens[0];
if(matricing){
if(type==MATRIX_DEL){
PWM pwm(matrixlines);
pwms.push_back(pwm);
matricing=false;
matrixlines.erase(matrixli
// cout << "erase matrices\n";
}
else{
matrixlines.push_back(line
}
}else if(type==FUNC_DEL){
//string::size_type firstwhitespace=trunc_line
string tok1=tokens[1];
int functype=(int)strtol(tok1.
// cout << "adding function\n";
vector<double> args;
int start=(int) strtol(tokens[2].c_str(), NULL, 10);
for(int i=3; i<tokens.size(); i++){
args.push_back(strtod(toke
}
if(functype==0){
Multinomial m(start, args);
gaps.push_back(m);
}
// else if(functype==1){
// Gaussian g(strtod(tokens[2].c_str()
// gaps.push_back(g);
//}
}
else if(type==MATRIX_DEL){
//cout << "matricing\n";
matricing=true;
}
else if(type=="E"){
//cout << "done sucking in\n";
done=true;
}
//cout << "end of while\n";
}
//cout << "finished reading file\n";
Multinomial m2(min, max);
gaps.push_back(m2);
//cout << "nullity at end is "<< gaps[gaps.size()-1].isFree
readFile.close();
}
antoniogm:
> Within MMotif (reproduced below), I define vector<GapFunction> gaps, and then
> proceed to push on various subclasses of GapFunction on to it. However, when
> I pull them off the vector and call a method, it defaults to the skeleton
> methods in GapFunction, rather than the overloaded methods defined in the
> various subclasses. In Java, I would cast the pulled-off object to the subclass
> and go from there, but in C++ I am somewhat lost. All help appreciated...Antonio.
In C++, when you want to overload a method, you have to declare that method as being "virtual". If you've already done that, then post the class definitions for GapFunction and Multinomial.
BTW, you said that declared "vector<GapFunction> gaps", but I see "vector<Multinomial> gaps". Which is it supposed to be?
Hope that helps,
Dex*
> Within MMotif (reproduced below), I define vector<GapFunction> gaps, and then
> proceed to push on various subclasses of GapFunction on to it. However, when
> I pull them off the vector and call a method, it defaults to the skeleton
> methods in GapFunction, rather than the overloaded methods defined in the
> various subclasses. In Java, I would cast the pulled-off object to the subclass
> and go from there, but in C++ I am somewhat lost. All help appreciated...Antonio.
In C++, when you want to overload a method, you have to declare that method as being "virtual". If you've already done that, then post the class definitions for GapFunction and Multinomial.
BTW, you said that declared "vector<GapFunction> gaps", but I see "vector<Multinomial> gaps". Which is it supposed to be?
Hope that helps,
Dex*
Lil' explanation from the VC++ docs:
Virtual Function
C++ Specific —>
A virtual function is a member function that you expect to be redefined in derived classes. When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class's version of the function.
END C++ Specific
Example 1
class WageEmployee
{
public:
virtual float computePay();
};
class SalesPerson : public WageEmployee
{
public:
float computePay();
};
You can execute different versions of computePay( ) depending on the type of object you're calling it for.
Example 2
WageEmployee aWorker;
SalesPerson aSeller;
WageEmployee *wagePtr;
wagePtr = &aWorker;
wagePtr->computePay(); // call WageEmployee::computePay
wagePtr = &aSeller;
wagePtr->computePay(); // call SalesPerson::computePay
The virtual keyword is needed only in the base class's declaration of the function; any subsequent declarations in derived classes are virtual by default.
A derived class's version of a virtual function must have the same parameter list and return type as those of the base class. If these are different, the function is not considered a redefinition of the virtual function. A redefined virtual function cannot differ from the original only by return type.
Virtual Function
C++ Specific —>
A virtual function is a member function that you expect to be redefined in derived classes. When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class's version of the function.
END C++ Specific
Example 1
class WageEmployee
{
public:
virtual float computePay();
};
class SalesPerson : public WageEmployee
{
public:
float computePay();
};
You can execute different versions of computePay( ) depending on the type of object you're calling it for.
Example 2
WageEmployee aWorker;
SalesPerson aSeller;
WageEmployee *wagePtr;
wagePtr = &aWorker;
wagePtr->computePay(); // call WageEmployee::computePay
wagePtr = &aSeller;
wagePtr->computePay(); // call SalesPerson::computePay
The virtual keyword is needed only in the base class's declaration of the function; any subsequent declarations in derived classes are virtual by default.
A derived class's version of a virtual function must have the same parameter list and return type as those of the base class. If these are different, the function is not considered a redefinition of the virtual function. A redefined virtual function cannot differ from the original only by return type.
Here's is a similar kind of question and some useful discussion on the same
https://www.experts-exchange.com/questions/20783912/Overloading-inherited-functions.html
Hope this helps
https://www.experts-exchange.com/questions/20783912/Overloading-inherited-functions.html
Hope this helps
ASKER
I still get compilation errors. I am posting GapFunction.h, Null.h ( a null prob. dist. that always returns 0.0, and with maximal range of inputs), and the new MMotif.h.
#ifndef GF_FLAG
#define GF_FLAG
#include <iostream>
#include <string>
class GapFunction{
public:
virtual double func(int i);
virtual int lowerBound();
virtual int upperBound();
};
#endif
#ifndef NULL_FLAG
#define NULL_FLAG
#include <iostream>
#include <string>
#include "GapFunction.h"
#include <math.h>
#include <vector>
#include <limits.h>
class Null: public GapFunction
{
public:
Null(){;}
double func(int i){
return 0.0;
}
int lowerBound(){
cout << "calling lowerbound in null\n";
return 1;
}
int upperBound(){
return INT_MAX;
}
};
#endif
#include <string>
#include <map>
#include <math.h>
#include <vector>
//#include <ot/util/StringTokenizer.h >
#include "PWM.h"
#include "GapFunction.h"
#include "Gaussian.h"
#include "Free.h"
#include "Multinomial.h"
#include "Null.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <limits.h>
using namespace std;
class MMotif{
public:
vector<PWM> pwms;
PWM backgr;
vector<GapFunction> gaps;
string MATRIX_DEL;
string FUNC_DEL;
static int const MMotif::maxlength=1000;
static int const MMotif::minlength=1;
/*MMotif(const vector<PWM>& p,
const vector<GapFunction>& g) {
if (p.size() != g.size() + 1) {
std::cout << "PWMs and GapFunctions not numbered accordingly" << std::endl;
} else {
pwms.assign(p.begin(), p.end()); // no need for a loop; use stl
gaps.assign(g.begin(), g.end());
}
}*/
MMotif(char *name){
MATRIX_DEL="M";
FUNC_DEL="F";
Null n1;
gaps.push_back(n1);
//cout << "multinomial nullity is " << gaps[0].isFree()<<endl;
ifstream readFile(name, ios::in);
char s[100]; // declares variable to read data from file
vector<string> matrixlines;
bool matricing=false;
bool done=false;
while(!done) {
// cout << readFile.eof() << endl;
readFile.getline(s, 100);
string line(s);
// cout << line << endl;
string buf; // Have a buffer string
stringstream ss(line); //insert the string into a stream
vector<string> tokens; // Create vector to hold our words
while (ss >> buf){
tokens.push_back(buf);
}
//string::size_type firstwhitespace=line.find_ first_of(" ", 0);
//string type=line.substr(0, firstwhitespace);
//string trunc_line=line.substr(fir stwhitespa ce, line.size());
string type=tokens[0];
if(matricing){
if(type==MATRIX_DEL){
PWM pwm(matrixlines);
pwms.push_back(pwm);
matricing=false;
matrixlines.erase(matrixli nes.begin( ), matrixlines.end());
// cout << "erase matrices\n";
}
else{
matrixlines.push_back(line );
}
}else if(type==FUNC_DEL){
//string::size_type firstwhitespace=trunc_line .find_firs t_of(" ", 0);
string tok1=tokens[1];
int functype=(int)strtol(tok1. c_str(), NULL, 10);
// cout << "adding function\n";
vector<double> args;
int start=(int) strtol(tokens[2].c_str(), NULL, 10);
for(int i=3; i<tokens.size(); i++){
args.push_back(strtod(toke ns[3].c_st r(), NULL));
}
if(functype==0){
Multinomial m(start, args);
gaps.push_back(m);
}
else if(functype==1){
Gaussian g(strtod(tokens[2].c_str() , NULL), strtod(tokens[3].c_str(), NULL));
gaps.push_back(g);
}
}
else if(type==MATRIX_DEL){
//cout << "matricing\n";
matricing=true;
}
else if(type=="E"){
//cout << "done sucking in\n";
done=true;
}
//cout << "end of while\n";
}
//cout << "finished reading file\n";
Null n2;
gaps.push_back(n2);
//cout << "nullity at end is "<< gaps[gaps.size()-1].isFree () << endl;
readFile.close();
}
double scoreSeq(const std::string str){
return score(pwms.size()-1, gaps.size()-1, str);
}
double score(int m, int g, const std::string& str){
cout << "running with motif " << m<< " gap " << g << " str " << str << endl;
if(g==0){
cout << "in last gap"<<endl;
return 0.0;
}
else if(str.length()==0){
cout << "string ended\n";
return -10000;
}
else{
if(g==m+1){
cout <<"in gap mode with gaps " << gaps.size()<< "\n";
int lower=gaps[g].lowerBound() ;
int upper=gaps[g].upperBound() ;
double max=-10000;
double gapvalue=-10000;
cout << " lower upper " << lower << " " << upper << endl;
for(int i=lower; i<=upper; i++){
gapvalue=gaps[g].func(i) + score(m, g-1, str.substr(i, str.length()-1));
cout << "value at gap "<< i << " " << gapvalue << endl;
if(gapvalue>max){
// cout<< "doing comparison\n";
max=gapvalue;
}
}
return max;
}else if(g==m){
double pwmvalue=-10000;
pwmvalue=pwms[m].score( str.substr(0, pwms[m].length() ) )
+ this->score( m-1, g, str.substr(pwms[m].length( ), str.length()-pwms[m].lengt h()));
return pwmvalue;
}
/*if(pwmvalue>gapvalue){
cout<< "went with the pwm\n";
return pwmvalue;
}else{
cout<< "went with the gap\n";
return gapvalue;
}
//cout << gaps[l].func(k)<< endl;
//cout << pwms[l].score( str.substr(0, pwms[l].length() ) )<< endl;
return MMotif::max(
gaps[l].func(k + 1 ) - gaps[l].func(k)+ score(l, k + 1, str.substr(1, str.length()-1)),
pwms[l].score(str.substr(0 , pwms[l].length() ) )
+ this->score( l - 1, 0, str.substr(pwms[l].length( ), str.length()-pwms[l].lengt h()))
); // max
}*/
}
}
double max(double first, double second){
if(first>=second){
cout << "returning first arg " << first << endl;
return first;
}else{
cout << "returning second arg " << second << endl;
return second;
}
}
private:
};
#ifndef GF_FLAG
#define GF_FLAG
#include <iostream>
#include <string>
class GapFunction{
public:
virtual double func(int i);
virtual int lowerBound();
virtual int upperBound();
};
#endif
#ifndef NULL_FLAG
#define NULL_FLAG
#include <iostream>
#include <string>
#include "GapFunction.h"
#include <math.h>
#include <vector>
#include <limits.h>
class Null: public GapFunction
{
public:
Null(){;}
double func(int i){
return 0.0;
}
int lowerBound(){
cout << "calling lowerbound in null\n";
return 1;
}
int upperBound(){
return INT_MAX;
}
};
#endif
#include <string>
#include <map>
#include <math.h>
#include <vector>
//#include <ot/util/StringTokenizer.h
#include "PWM.h"
#include "GapFunction.h"
#include "Gaussian.h"
#include "Free.h"
#include "Multinomial.h"
#include "Null.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <limits.h>
using namespace std;
class MMotif{
public:
vector<PWM> pwms;
PWM backgr;
vector<GapFunction> gaps;
string MATRIX_DEL;
string FUNC_DEL;
static int const MMotif::maxlength=1000;
static int const MMotif::minlength=1;
/*MMotif(const vector<PWM>& p,
const vector<GapFunction>& g) {
if (p.size() != g.size() + 1) {
std::cout << "PWMs and GapFunctions not numbered accordingly" << std::endl;
} else {
pwms.assign(p.begin(), p.end()); // no need for a loop; use stl
gaps.assign(g.begin(), g.end());
}
}*/
MMotif(char *name){
MATRIX_DEL="M";
FUNC_DEL="F";
Null n1;
gaps.push_back(n1);
//cout << "multinomial nullity is " << gaps[0].isFree()<<endl;
ifstream readFile(name, ios::in);
char s[100]; // declares variable to read data from file
vector<string> matrixlines;
bool matricing=false;
bool done=false;
while(!done) {
// cout << readFile.eof() << endl;
readFile.getline(s, 100);
string line(s);
// cout << line << endl;
string buf; // Have a buffer string
stringstream ss(line); //insert the string into a stream
vector<string> tokens; // Create vector to hold our words
while (ss >> buf){
tokens.push_back(buf);
}
//string::size_type firstwhitespace=line.find_
//string type=line.substr(0, firstwhitespace);
//string trunc_line=line.substr(fir
string type=tokens[0];
if(matricing){
if(type==MATRIX_DEL){
PWM pwm(matrixlines);
pwms.push_back(pwm);
matricing=false;
matrixlines.erase(matrixli
// cout << "erase matrices\n";
}
else{
matrixlines.push_back(line
}
}else if(type==FUNC_DEL){
//string::size_type firstwhitespace=trunc_line
string tok1=tokens[1];
int functype=(int)strtol(tok1.
// cout << "adding function\n";
vector<double> args;
int start=(int) strtol(tokens[2].c_str(), NULL, 10);
for(int i=3; i<tokens.size(); i++){
args.push_back(strtod(toke
}
if(functype==0){
Multinomial m(start, args);
gaps.push_back(m);
}
else if(functype==1){
Gaussian g(strtod(tokens[2].c_str()
gaps.push_back(g);
}
}
else if(type==MATRIX_DEL){
//cout << "matricing\n";
matricing=true;
}
else if(type=="E"){
//cout << "done sucking in\n";
done=true;
}
//cout << "end of while\n";
}
//cout << "finished reading file\n";
Null n2;
gaps.push_back(n2);
//cout << "nullity at end is "<< gaps[gaps.size()-1].isFree
readFile.close();
}
double scoreSeq(const std::string str){
return score(pwms.size()-1, gaps.size()-1, str);
}
double score(int m, int g, const std::string& str){
cout << "running with motif " << m<< " gap " << g << " str " << str << endl;
if(g==0){
cout << "in last gap"<<endl;
return 0.0;
}
else if(str.length()==0){
cout << "string ended\n";
return -10000;
}
else{
if(g==m+1){
cout <<"in gap mode with gaps " << gaps.size()<< "\n";
int lower=gaps[g].lowerBound()
int upper=gaps[g].upperBound()
double max=-10000;
double gapvalue=-10000;
cout << " lower upper " << lower << " " << upper << endl;
for(int i=lower; i<=upper; i++){
gapvalue=gaps[g].func(i) + score(m, g-1, str.substr(i, str.length()-1));
cout << "value at gap "<< i << " " << gapvalue << endl;
if(gapvalue>max){
// cout<< "doing comparison\n";
max=gapvalue;
}
}
return max;
}else if(g==m){
double pwmvalue=-10000;
pwmvalue=pwms[m].score( str.substr(0, pwms[m].length() ) )
+ this->score( m-1, g, str.substr(pwms[m].length(
return pwmvalue;
}
/*if(pwmvalue>gapvalue){
cout<< "went with the pwm\n";
return pwmvalue;
}else{
cout<< "went with the gap\n";
return gapvalue;
}
//cout << gaps[l].func(k)<< endl;
//cout << pwms[l].score( str.substr(0, pwms[l].length() ) )<< endl;
return MMotif::max(
gaps[l].func(k + 1 ) - gaps[l].func(k)+ score(l, k + 1, str.substr(1, str.length()-1)),
pwms[l].score(str.substr(0
+ this->score( l - 1, 0, str.substr(pwms[l].length(
); // max
}*/
}
}
double max(double first, double second){
if(first>=second){
cout << "returning first arg " << first << endl;
return first;
}else{
cout << "returning second arg " << second << endl;
return second;
}
}
private:
};
>>I still get compilation errors
Um, my crystal ball is still on repair - what errors?
Um, my crystal ball is still on repair - what errors?
ASKER
g++ score.cpp
/tmp/ccSDUD7r.o(.gnu.linko nce.d.__vt _8Gaussian +0x8): undefined reference to `GapFunction::func(int)'
/tmp/ccSDUD7r.o(.gnu.linko nce.d.__vt _8Gaussian +0xc): undefined reference to `GapFunction::lowerBound(v oid)'
/tmp/ccSDUD7r.o(.gnu.linko nce.d.__vt _8Gaussian +0x10): undefined reference to `GapFunction::upperBound(v oid)'
/tmp/ccSDUD7r.o: In function `GapFunction::GapFunction( void)':
/tmp/ccSDUD7r.o(.GapFuncti on::gnu.li nkonce.t.( void)+0x8) : undefined reference to `GapFunction virtual table'
/tmp/ccSDUD7r.o: In function `GapFunction::GapFunction( GapFunctio n const &)':
/tmp/ccSDUD7r.o(.GapFuncti on::gnu.li nkonce.t.( GapFunctio n const &)+0xb): undefined reference to `GapFunction virtual table'
/tmp/ccSDUD7r.o: In function `Gaussian type_info function':
/tmp/ccSDUD7r.o(.gnu.linko nce.t.__tf 8Gaussian+ 0x10): undefined reference to `GapFunction type_info function'
/tmp/ccSDUD7r.o(.gnu.linko nce.t.__tf 8Gaussian+ 0x18): undefined reference to `GapFunction type_info node'
/tmp/ccSDUD7r.o: In function `Multinomial type_info function':
/tmp/ccSDUD7r.o(.gnu.linko nce.t.__tf 11Multinom ial+0x10): undefined reference to `GapFunction type_info function'
/tmp/ccSDUD7r.o(.gnu.linko nce.t.__tf 11Multinom ial+0x18): undefined reference to `GapFunction type_info node'
/tmp/ccSDUD7r.o: In function `Null type_info function':
/tmp/ccSDUD7r.o(.gnu.linko nce.t.__tf 4Null+0x10 ): undefined reference to `GapFunction type_info function'
/tmp/ccSDUD7r.o(.gnu.linko nce.t.__tf 4Null+0x18 ): undefined reference to `GapFunction type_info node'
collect2: ld returned 1 exit status
To me at least, not particularly informative....
/tmp/ccSDUD7r.o(.gnu.linko
/tmp/ccSDUD7r.o(.gnu.linko
/tmp/ccSDUD7r.o(.gnu.linko
/tmp/ccSDUD7r.o: In function `GapFunction::GapFunction(
/tmp/ccSDUD7r.o(.GapFuncti
/tmp/ccSDUD7r.o: In function `GapFunction::GapFunction(
/tmp/ccSDUD7r.o(.GapFuncti
/tmp/ccSDUD7r.o: In function `Gaussian type_info function':
/tmp/ccSDUD7r.o(.gnu.linko
/tmp/ccSDUD7r.o(.gnu.linko
/tmp/ccSDUD7r.o: In function `Multinomial type_info function':
/tmp/ccSDUD7r.o(.gnu.linko
/tmp/ccSDUD7r.o(.gnu.linko
/tmp/ccSDUD7r.o: In function `Null type_info function':
/tmp/ccSDUD7r.o(.gnu.linko
/tmp/ccSDUD7r.o(.gnu.linko
collect2: ld returned 1 exit status
To me at least, not particularly informative....
Even though the 'GapFunction' members do nothing, they either have to be 'pure virtual' or you have to provide a minimal implementation, e.g.
// minimal impl.
class GapFunction{
public:
virtual double func(int i) { return 0.0;};
virtual int lowerBound() { return 0;};
virtual int upperBound(){ return 0;};
};
// pure virtual
class GapFunction{
public:
virtual double func(int i) = 0;
virtual int lowerBound() = 0;
virtual int upperBound() = 0;
};
// minimal impl.
class GapFunction{
public:
virtual double func(int i) { return 0.0;};
virtual int lowerBound() { return 0;};
virtual int upperBound(){ return 0;};
};
// pure virtual
class GapFunction{
public:
virtual double func(int i) = 0;
virtual int lowerBound() = 0;
virtual int upperBound() = 0;
};
ASKER
I made the above changes, and now get something of the form:
cd /home/agm/C++/MPattern/
g++ score.cpp
/usr/include/g++-3/stl_con struct.h: In function `void construct (_T1 *,
const _T2 &) [with _T1 = GapFunction, _T2 = GapFunction]':
/usr/include/g++-3/stl_vec tor.h:321: instantiated from `vector<_Tp, _Alloc>::push_back (const _Tp &) [with _Tp = GapFunction, _Alloc = allocator<GapFunction>]'
MMotif.h:42: instantiated from here
/usr/include/g++-3/stl_con struct.h:4 8: cannot allocate an object of
type `GapFunction'
/usr/include/g++-3/stl_con struct.h:4 8: since the following virtual
functions are abstract:
GapFunction.h:10: int GapFunction::upperBound ()
GapFunction.h:9: int GapFunction::lowerBound ()
GapFunction.h:8: double GapFunction::func (int)
/usr/include/g++-3/stl_vec tor.h: In method `void vector<_Tp,
_Alloc>::_M_insert_aux (_Tp *, const _Tp &) [with _Tp = GapFunction,
_Alloc = allocator<GapFunction>]':
/usr/include/g++-3/stl_vec tor.h:325: instantiated from `vector<_Tp, _Alloc>::push_back (const _Tp &) [with _Tp = GapFunction, _Alloc = allocator<GapFunction>]'
MMotif.h:42: instantiated from here
/usr/include/g++-3/stl_vec tor.h:593: cannot declare variable `__x_copy'
to be of type `GapFunction'
/usr/include/g++-3/stl_vec tor.h:593: since type `GapFunction' has
abstract virtual functions
/usr/include/g++-3/stl_vec tor.h:593: cannot allocate an object of type
`GapFunction'
/usr/include/g++-3/stl_vec tor.h:593: since type `GapFunction' has
abstract virtual functions
cd /home/agm/C++/MPattern/
g++ score.cpp
/usr/include/g++-3/stl_con
const _T2 &) [with _T1 = GapFunction, _T2 = GapFunction]':
/usr/include/g++-3/stl_vec
MMotif.h:42: instantiated from here
/usr/include/g++-3/stl_con
type `GapFunction'
/usr/include/g++-3/stl_con
functions are abstract:
GapFunction.h:10: int GapFunction::upperBound ()
GapFunction.h:9: int GapFunction::lowerBound ()
GapFunction.h:8: double GapFunction::func (int)
/usr/include/g++-3/stl_vec
_Alloc>::_M_insert_aux (_Tp *, const _Tp &) [with _Tp = GapFunction,
_Alloc = allocator<GapFunction>]':
/usr/include/g++-3/stl_vec
MMotif.h:42: instantiated from here
/usr/include/g++-3/stl_vec
to be of type `GapFunction'
/usr/include/g++-3/stl_vec
abstract virtual functions
/usr/include/g++-3/stl_vec
`GapFunction'
/usr/include/g++-3/stl_vec
abstract virtual functions
OK, I forgot about that - this way, you should use the "minimal" approach
ASKER
Ok, the hackery works now and the compiler doesn't complain, but I am still getting the same fundamental error of the function call going to the superclass rather than the subclass. The below test script:
#include <iostream>
#include "Null.h"
using namespace std;
void main(){
Null n;
cout<< n.lowerBound()<<endl;
cout<< n.upperBound()<<endl;
vector<GapFunction> gaps;
gaps.push_back(n);
cout<<gaps[0].lowerBound() << endl;
}
returns:
1
2147483647
0
#include <iostream>
#include "Null.h"
using namespace std;
void main(){
Null n;
cout<< n.lowerBound()<<endl;
cout<< n.upperBound()<<endl;
vector<GapFunction> gaps;
gaps.push_back(n);
cout<<gaps[0].lowerBound()
}
returns:
1
2147483647
0
Make it read
include <iostream>
#include "Null.h"
using namespace std;
void main(){
Null n;
cout<< n.lowerBound()<<endl;
cout<< n.upperBound()<<endl;
vector<GapFunction&> gaps; // <--!!!
gaps.push_back(n);
cout<<gaps[0].lowerBound() << endl;
}
As the above explanation says:
"A virtual function is a member function that you expect to be redefined in derived classes. When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class's version of the function."
As you were storing instances of 'GapFunction' objects and not pointers or references, you were still calling the base class member functions.
include <iostream>
#include "Null.h"
using namespace std;
void main(){
Null n;
cout<< n.lowerBound()<<endl;
cout<< n.upperBound()<<endl;
vector<GapFunction&> gaps; // <--!!!
gaps.push_back(n);
cout<<gaps[0].lowerBound()
}
As the above explanation says:
"A virtual function is a member function that you expect to be redefined in derived classes. When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class's version of the function."
As you were storing instances of 'GapFunction' objects and not pointers or references, you were still calling the base class member functions.
ASKER
I do that and get:
cd /home/agm/C++/MPattern/
g++ test2.cpp
/usr/include/g++-3/stl_vec
test2.cpp:8: instantiated from `_Vector_base<GapFunction &, allocator<GapFunction &> >'
test2.cpp:8: instantiated from `vector<GapFunction &, allocator<GapFunction &> >'
test2.cpp:8: instantiated from here
/usr/include/g++-3/stl_vec
`GapFunction &'
/usr/include/g++-3/stl_vec
`GapFunction &'
/usr/include/g++-3/stl_vec
`GapFunction &'
/usr/include/g++-3/stl_vec
`GapFunction &'
/usr/include/g++-3/stl_vec
`GapFunction &'
/usr/include/g++-3/stl_vec
test2.cpp:8: instantiated from here
/usr/include/g++-3/stl_vec
`GapFunction &'
/usr/include/g++-3/stl_vec
`GapFunction &const'
/usr/include/g++-3/stl_vec
`GapFunction &'
/usr/include/g++-3/stl_vec
`GapFunction &const'
/usr/include/g++-3/stl_vec
type `GapFunction &'
/usr/include/g++-3/stl_vec
type `GapFunction &const'
/usr/include/g++-3/stl_vec
`GapFunction &const'
/usr/include/g++-3/stl_vec
/usr/include/g++-3/stl_vec
`GapFunction &'
/usr/include/g++-3/stl_vec
/usr/include/g++-3/stl_vec
type `GapFunction &const'
/usr/include/g++-3/stl_vec
`GapFunction &'
/usr/include/g++-3/stl_vec
`GapFunction &'
/usr/include/g++-3/stl_vec
`GapFunction &const'
/usr/include/g++-3/stl_vec
`GapFunction &'
/usr/include/g++-3/stl_vec
`GapFunction &const'
/usr/include/g++-3/stl_vec
`GapFunction &'
/usr/include/g++-3/stl_vec
/usr/include/g++-3/stl_vec
`GapFunction &const'
/usr/include/g++-3/stl_vec
/usr/include/g++-3/stl_vec
`GapFunction &'
/usr/include/g++-3/stl_vec
/usr/include/g++-3/stl_vec
`GapFunction &const'
/usr/include/g++-3/stl_vec
/usr/include/g++-3/stl_vec
type `GapFunction &'
/usr/include/g++-3/stl_vec
type `GapFunction &const'
/usr/include/g++-3/stl_vec
type `GapFunction &const'
/usr/include/g++-3/stl_vec
type `GapFunction &const'
/usr/include/g++-3/stl_vec
type `GapFunction &'
/usr/include/g++-3/stl_vec
type `GapFunction &const'
/usr/include/g++-3/stl_vec
type `GapFunction &'
/usr/include/g++-3/stl_vec
type `GapFunction &const'
/usr/include/g++-3/stl_vec
type `GapFunction &const'
/usr/include/g++-3/stl_vec
`GapFunction &'
/usr/include/g++-3/stl_vec
`GapFunction &'
/usr/include/g++-3/stl_vec
`GapFunction &'
/usr/include/g++-3/stl_vec
bailing out
Compilation exited abnormally with code 1 at Fri Oct 31 15:40:19
ASKER
Look, at this point maybe we need faster communication to resolve this rather than bouncing slowly via the site. I am antoniofgm on aim, or malvoglio on ymessenger. Or email me directly at agm at socrates.berkeley.edu
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Sorry, direct email is against the site rules :o)
ASKER
Pointer approach worked. Thanks so much for your time and instantaneous responses...500 points on the way.
ASKER
Just never ends....
Now it throws a segmentation fault. Seems like it doesnt' like calling functions on objects from the vector. Note that I do a test at the end of the constructor to see that the Null GapFunction works. But then later does not work inside of score()....
class MMotif{
public:
vector<PWM> pwms;
PWM backgr;
vector<GapFunction*> gaps;
string MATRIX_DEL;
string FUNC_DEL;
static int const MMotif::maxlength=1000;
static int const MMotif::minlength=1;
/*MMotif(const vector<PWM>& p,
const vector<GapFunction>& g) {
if (p.size() != g.size() + 1) {
std::cout << "PWMs and GapFunctions not numbered accordingly" << std::endl;
} else {
pwms.assign(p.begin(), p.end()); // no need for a loop; use stl
gaps.assign(g.begin(), g.end());
}
}*/
MMotif(char *name){
MATRIX_DEL="M";
FUNC_DEL="F";
Null n1;
gaps.push_back(&n1);
//cout << "multinomial nullity is " << gaps[0].isFree()<<endl;
ifstream readFile(name, ios::in);
char s[100]; // declares variable to read data from file
vector<string> matrixlines;
bool matricing=false;
bool done=false;
while(!done) {
// cout << readFile.eof() << endl;
readFile.getline(s, 100);
string line(s);
// cout << line << endl;
string buf; // Have a buffer string
stringstream ss(line); //insert the string into a stream
vector<string> tokens; // Create vector to hold our words
while (ss >> buf){
tokens.push_back(buf);
}
//string::size_type firstwhitespace=line.find_ first_of(" ", 0);
//string type=line.substr(0, firstwhitespace);
//string trunc_line=line.substr(fir stwhitespa ce, line.size());
string type=tokens[0];
if(matricing){
if(type==MATRIX_DEL){
PWM pwm(matrixlines);
pwms.push_back(pwm);
matricing=false;
matrixlines.erase(matrixli nes.begin( ), matrixlines.end());
// cout << "erase matrices\n";
}
else{
matrixlines.push_back(line );
}
}else if(type==FUNC_DEL){
//string::size_type firstwhitespace=trunc_line .find_firs t_of(" ", 0);
string tok1=tokens[1];
int functype=(int)strtol(tok1. c_str(), NULL, 10);
// cout << "adding function\n";
vector<double> args;
int start=(int) strtol(tokens[2].c_str(), NULL, 10);
for(int i=3; i<tokens.size(); i++){
args.push_back(strtod(toke ns[3].c_st r(), NULL));
}
if(functype==0){
Multinomial m(start, args);
gaps.push_back(&m);
}
else if(functype==1){
Gaussian g((int) strtod(tokens[2].c_str(), NULL), strtod(tokens[3].c_str(), NULL), (int)strtod(tokens[4].c_st r(), NULL), (int)strtod(tokens[5].c_st r(), NULL));
gaps.push_back(&g);
}
}
else if(type==MATRIX_DEL){
//cout << "matricing\n";
matricing=true;
}
else if(type=="E"){
//cout << "done sucking in\n";
done=true;
}
//cout << "end of while\n";
}
//cout << "finished reading file\n";
Null n2;
gaps.push_back(&n2);
cout << "gap at end is " << gaps[gaps.size()-1]->func( 0) << endl;
readFile.close();
}
double scoreSeq(const std::string str){
return score(pwms.size()-1, gaps.size()-1, str);
}
double score(int m, int g, const std::string& str){
cout << "running with motif " << m<< " gap " << g << " str " << str << endl;
if(g==0){
cout << "in last gap"<<endl;
return 0.0;
}
else if(str.length()==0){
cout << "string ended\n";
return -10000;
}
else{
if(g==m+1){
cout <<"in gap mode with gaps " << g << "and no of gaps "<<gaps.size()<<"\n";
gaps[0]->func(0);
cout << "finished stupid thing\n";
cout<<gaps[0]->lowerBound( )<<endl;
int lower=gaps[g]->lowerBound( );
int upper=gaps[g]->upperBound( );
double max=-10000;
double gapvalue=-10000;
cout << " lower upper " << lower << " " << upper << endl;
for(int i=lower; i<=upper; i++){
gapvalue=gaps[g]->func(i) + score(m, g-1, str.substr(i, str.length()-1));
cout << "value at gap "<< i << " " << gapvalue << endl;
if(gapvalue>max){
// cout<< "doing comparison\n";
max=gapvalue;
}
}
return max;
}else if(g==m){
double pwmvalue=-10000;
pwmvalue=pwms[m].score( str.substr(0, pwms[m].length() ) )
+ this->score( m-1, g, str.substr(pwms[m].length( ), str.length()-pwms[m].lengt h()));
return pwmvalue;
}
/*if(pwmvalue>gapvalue){
cout<< "went with the pwm\n";
return pwmvalue;
}else{
cout<< "went with the gap\n";
return gapvalue;
}
//cout << gaps[l].func(k)<< endl;
//cout << pwms[l].score( str.substr(0, pwms[l].length() ) )<< endl;
return MMotif::max(
gaps[l].func(k + 1 ) - gaps[l].func(k)+ score(l, k + 1, str.substr(1, str.length()-1)),
pwms[l].score(str.substr(0 , pwms[l].length() ) )
+ this->score( l - 1, 0, str.substr(pwms[l].length( ), str.length()-pwms[l].lengt h()))
); // max
}*/
}
}
double max(double first, double second){
if(first>=second){
cout << "returning first arg " << first << endl;
return first;
}else{
cout << "returning second arg " << second << endl;
return second;
}
}
private:
};
produces
gap at end is 0
running with motif 1 gap 2 str AGCTAAAAGCT
Segmentation fault
Now it throws a segmentation fault. Seems like it doesnt' like calling functions on objects from the vector. Note that I do a test at the end of the constructor to see that the Null GapFunction works. But then later does not work inside of score()....
class MMotif{
public:
vector<PWM> pwms;
PWM backgr;
vector<GapFunction*> gaps;
string MATRIX_DEL;
string FUNC_DEL;
static int const MMotif::maxlength=1000;
static int const MMotif::minlength=1;
/*MMotif(const vector<PWM>& p,
const vector<GapFunction>& g) {
if (p.size() != g.size() + 1) {
std::cout << "PWMs and GapFunctions not numbered accordingly" << std::endl;
} else {
pwms.assign(p.begin(), p.end()); // no need for a loop; use stl
gaps.assign(g.begin(), g.end());
}
}*/
MMotif(char *name){
MATRIX_DEL="M";
FUNC_DEL="F";
Null n1;
gaps.push_back(&n1);
//cout << "multinomial nullity is " << gaps[0].isFree()<<endl;
ifstream readFile(name, ios::in);
char s[100]; // declares variable to read data from file
vector<string> matrixlines;
bool matricing=false;
bool done=false;
while(!done) {
// cout << readFile.eof() << endl;
readFile.getline(s, 100);
string line(s);
// cout << line << endl;
string buf; // Have a buffer string
stringstream ss(line); //insert the string into a stream
vector<string> tokens; // Create vector to hold our words
while (ss >> buf){
tokens.push_back(buf);
}
//string::size_type firstwhitespace=line.find_
//string type=line.substr(0, firstwhitespace);
//string trunc_line=line.substr(fir
string type=tokens[0];
if(matricing){
if(type==MATRIX_DEL){
PWM pwm(matrixlines);
pwms.push_back(pwm);
matricing=false;
matrixlines.erase(matrixli
// cout << "erase matrices\n";
}
else{
matrixlines.push_back(line
}
}else if(type==FUNC_DEL){
//string::size_type firstwhitespace=trunc_line
string tok1=tokens[1];
int functype=(int)strtol(tok1.
// cout << "adding function\n";
vector<double> args;
int start=(int) strtol(tokens[2].c_str(), NULL, 10);
for(int i=3; i<tokens.size(); i++){
args.push_back(strtod(toke
}
if(functype==0){
Multinomial m(start, args);
gaps.push_back(&m);
}
else if(functype==1){
Gaussian g((int) strtod(tokens[2].c_str(), NULL), strtod(tokens[3].c_str(), NULL), (int)strtod(tokens[4].c_st
gaps.push_back(&g);
}
}
else if(type==MATRIX_DEL){
//cout << "matricing\n";
matricing=true;
}
else if(type=="E"){
//cout << "done sucking in\n";
done=true;
}
//cout << "end of while\n";
}
//cout << "finished reading file\n";
Null n2;
gaps.push_back(&n2);
cout << "gap at end is " << gaps[gaps.size()-1]->func(
readFile.close();
}
double scoreSeq(const std::string str){
return score(pwms.size()-1, gaps.size()-1, str);
}
double score(int m, int g, const std::string& str){
cout << "running with motif " << m<< " gap " << g << " str " << str << endl;
if(g==0){
cout << "in last gap"<<endl;
return 0.0;
}
else if(str.length()==0){
cout << "string ended\n";
return -10000;
}
else{
if(g==m+1){
cout <<"in gap mode with gaps " << g << "and no of gaps "<<gaps.size()<<"\n";
gaps[0]->func(0);
cout << "finished stupid thing\n";
cout<<gaps[0]->lowerBound(
int lower=gaps[g]->lowerBound(
int upper=gaps[g]->upperBound(
double max=-10000;
double gapvalue=-10000;
cout << " lower upper " << lower << " " << upper << endl;
for(int i=lower; i<=upper; i++){
gapvalue=gaps[g]->func(i) + score(m, g-1, str.substr(i, str.length()-1));
cout << "value at gap "<< i << " " << gapvalue << endl;
if(gapvalue>max){
// cout<< "doing comparison\n";
max=gapvalue;
}
}
return max;
}else if(g==m){
double pwmvalue=-10000;
pwmvalue=pwms[m].score( str.substr(0, pwms[m].length() ) )
+ this->score( m-1, g, str.substr(pwms[m].length(
return pwmvalue;
}
/*if(pwmvalue>gapvalue){
cout<< "went with the pwm\n";
return pwmvalue;
}else{
cout<< "went with the gap\n";
return gapvalue;
}
//cout << gaps[l].func(k)<< endl;
//cout << pwms[l].score( str.substr(0, pwms[l].length() ) )<< endl;
return MMotif::max(
gaps[l].func(k + 1 ) - gaps[l].func(k)+ score(l, k + 1, str.substr(1, str.length()-1)),
pwms[l].score(str.substr(0
+ this->score( l - 1, 0, str.substr(pwms[l].length(
); // max
}*/
}
}
double max(double first, double second){
if(first>=second){
cout << "returning first arg " << first << endl;
return first;
}else{
cout << "returning second arg " << second << endl;
return second;
}
}
private:
};
produces
gap at end is 0
running with motif 1 gap 2 str AGCTAAAAGCT
Segmentation fault
Hope you don't mind if I check that tomorrow, but it's about 1am here&now :o)
ASKER
I am afraid I rather need an answer quickly. I am reposting a question with the new code...feel free to respond.
In C++, you'd make the 'GapFunction' methods 'virtual' in order to achieve the desired effect.