Why is my overloaded member function only "ambiguous" as a char and not an int and string?
I'm trying to create a one-code path for my Char class by funneling code through an overloaded equals() function. It works fine when I use equals as an int and string but is ambiguous as a char.
class Char
{
private:
char cData;
int iData;
string sData;
public:
//Mutators:
void equals(char c);
void equals(int c);
void equals(string c);
//Constructors:
Char(char c);
Char(int c);
Char(string c);
};
void Char::equals(char c)
{
cData = c;
}
void Char::equals(int c)
{
iData = c;
}
void Char::equals(string c)
{
sData = c;
}
Char::Char(char c)
{
this->equals(c); //Call to member function 'equals' is ambiguous
}
Char::Char(int c)
{
this->equals(c);
}
Char::Char(string c)
{
this->equals(c);
}
The error only happens for char, which is confusing since string works fine. I expected it to work for all of them since that's been the case so far.
It's ambiguous because if you do
Char c(42);
The compiler does not know whether it should call the char or int constructor. Both are an equally good match.
The same goes for equals(123);. Again, both the char and int overloads match and the compiler cannot tell which one you intend to call.
you can use a single equal method to accept a char or an int. like
void euqals(unsigned int c_i);
Related
I want to make an Animal class in c++ using string. But it look like by using string it show so much of error and doesn't get resolve. Can someone help me what is wrong in my code?
#include<iostream>
using namespace std;
class Animal {
char str1[100], str2[100], str3[100];
public :
void setData(char a, char b, char c);
void getData() {
cout<<"The type of animal is "<<str1[100]<<endl;
cout<<"The name of "<<str1[100]<<" is "<<str2[100]<<endl;
cout<<" "<<str1[100]<<" "<<str3[100]<<endl;
}
void Animal :: setData(char a, char b, char c) {
str1[100] = a;
str2[100] = b;
str3[100] = c;
}
int main() {
Animal isha;
isha.setData('D', 'T', 'B');
isha.getData();
return 0;
}
You have undefined behavior in your program because you're going out of bounds of the array str1, str2 and str3 in addition to syntax errors as explained below:
Problem 1
You're missing the closing brace } and a semicolon ; for the class. To solve this add }; at the end of the class definition as shown below.
Problem 2
Even after fixing the syntax error, you will have undefined behavior in your program because you're going out of bounds of the arrays str1, str2 and str3 when you wrote:
void getData() {
//----------------------------------vvvvvvvvv---------------->undefined behavior
cout<<"The type of animal is "<<str1[100]<<endl;
//------------------------vvvvvvvvv----------vvvvvvvvv------->undefined behavior
cout<<"The name of "<<str1[100]<<" is "<<str2[100]<<endl;
//-------------vvvvvvvvv-------vvvvvvvvv--------------------->undefined behavior
cout<<" "<<str1[100]<<" "<<str3[100]<<endl;
}
void Animal :: setData(char a, char b, char c) {
str1[100] = a; //undefined behavior
str2[100] = b;//undefined behavior
str3[100] = c;//undefined behavior
}
Solution
Better would be to use std::string instead of built in arrays and make sure that you're don't go out of bounds of the array(in case arrays are used) as shown below. The code given is a demonstration of how to fix the issues.
class Animal {
std::string str1, str2, str3;
public :
void setData(std::string a, std::string b, std::string c);
void getData() {
std::cout<<"The type of animal is "<<str1<<std::endl;
std::cout<<"The name of "<<str1<<" is "<<str2<<std::endl;
std::cout<<" "<<str1<<" "<<str3<<std::endl;
}
};
void Animal :: setData(std::string a, std::string b, std::string c) {
str1= a;
str2= b;
str3= c;
}
int main() {
Animal isha;
isha.setData("D", "T", "B");
isha.getData();
return 0;
}
One of the reasons why using std::string is better here in your example is that using char arrays is that while using char arrays in your original example, you were wasting space as each of those array were of length 100. By using std::string that wastage of space in longer there. Additionally, elements can be added and removed from a std::string and so this make the program more flexible.
#include<iostream>
class ravi
{
private:
char a[10],char b[10];
public:
void setdata(char x[10],char y[10])
{
a = x; b = y;
}
void show()
{
std::cout << a << b;
}
};
int main()
{
ravi r;
r.setdata("text","copied");
r.show();
}
i am trying to copy the strings "text" "copied" to x and y and i am getting an error that "incompatible types in assignment from char* to char" .can someone tell me what is wrong with my code.
Strings in C++ are std::string. You are using char arrays, aka C-strings, NUL terminated strings, etc. which are harder to manipulate.
Simply by replacing the type of a and b (and a minor improvement on the arguments of setdata, you get something working, plus some useful features of string:
#include <string>
class ravi
{
std::string a;
std::string b;
public:
void setdata(const char* x, const char* y)
{
a = x;
b = y;
}
void show()
{
std::cout << a << b;
}
};
If this is possible (regarding the API of ravi), try and use std::string const& in lieu of const char*:
void setdata(std::string const& x, std::string const& y)
With C++17, you'd better use std::string_view in lieu of const char* for argument types:
void setdata(std::string_view x, std::string_view y)
Arrays do not have the copy assignment operator. So these statements
a=x;b=y;
are invalid.
You should use standard C function strcpy or strncpy declared in the header <cstring> to copy character arrays. Also string literals in C++ have types of constant character arrays. So the parameters of the member function setdata should be declared with the qualifier const.
void setdata( const char x[], const char y[] )
{
strncpy( a, x, sizeof( a ) );
a[sizeof( a ) - 1] = '\0';
strncpy( b, x, sizeof( b ) );
b[sizeof( b ) - 1] = '\0';
}
Take into account that this statement is invalid
char a[10],char b[10];
Either you should write
char a[10]; char b[10];
or
char a[10], b[10];
Use the strcpy function from string.h:
#include <string.h>
void setdata(char x[10],char y[10])
{
strcpy(a,x);
strcpy(b,y);
}
I'm trying to overload operator "<<" in c++. I have a class called TCalendario, with 3 privates int attributes, and 3 public getters to return this variables in public mode, but when I try to save the return value of the getter in another int variable, i can't compile. The mensage error is:
"cannot convert 'TCalendario::Dia' from type 'int (TCalendario::)()' to type 'int'"
Private attributes:
private:
int dia, mes, anyo
And getters:
int TCalendario::Dia()
{
return dia;
}
int TCalendario::Mes()
{
return mes;
}
int TCalendario::Anyo()
{
return anyo;
}
The code that crashes when I try to compile is:
ostream& operator<<(ostream &x, TCalendario &c)
{
int day=c.Dia;
int month=c.Mes;
int year=c.Anyo;
}
In order to call a method without arguments, you need to put empty braces, like this:
int day=c.Dia();
You missed the () in function call
int day=c.Dia();
int month=c.Mes();
int year=c.Anyo();
I've got a class with 3 private variables and one public method, that has 2 char parameter variables.
class InitLine
{
private:
char *a;
char b, c;
public:
InitLine(char *inita, char initc);
Init(char *a, char c);
};
Now the definition of the method is simple:
Initline::Init(char *a, char c)
{
for (b=0; b<c; b++)
*(a+c)=0;
}
Now my question is: If I wish to repeat the same actions with different parametertypes (*a and c, or one of them becomes an integer e.g.), is it necessary to create a new class, or can I use the existing one, doing some 'typecasting' or some other trick I don't know yet?
Thanks and regards
Uwe
Use templates, make the Init function a template of your arguments type.
template <typename T>
Init(char*a , T c){}
for instance
You have many places in your code, which should be fixed prior to any further operations.
Naming convention is terrible. What is a, b, c?
You use b as a loop indexer, while a local variable should be used there instead.
You don't show us, what is a. Where is it allocated? What is the size of memory pointed to by a?
I guess, that your code should look like the following:
class InitLine
{
private:
char * data;
int count;
public:
InitLine(char * newData, int newCount)
{
// Possible error checking?
data = newData;
count = newCount;
}
// No parameters needed here, I guess
void Init()
{
for (int i = 0; i < count; i++)
data[i] = 0;
}
};
As for your question, I'm not really sure, what you are trying to achieve and what do you want to know. If you want to write a generic class holding any type of arrays, you have to use templates:
template <typename T>
class InitLine
{
private:
T * data;
int count;
public:
InitLine(T * newData, int newCount)
{
// Possible error checking?
data = newData;
count = newCount;
}
// No parameters needed here, I guess
void Init()
{
for (int i = 0; i < count; i++)
data[i] = 0;
}
};
You have to use this class in the following way:
InitLine<char> line(myData, myDataSize);
// where myData is a char * and myDataSize is an int
If you want to write a few methods differing by their parameters, this technique is called method overloading and is available in C++:
void Init(char * a, int b) { /* sth */ }
void Init(int * a, int b) { /* sth */ }
Note, that compiler must be able to clearly distinguish, which method should be called. Eg.
void Test(int a) { }
void Test(char a) { }
Test(0); // Ambiguity: which method should be called?
These are only things coming to my mind, while reading your question. If it is not what you are asking for, consider editing the question to be more specific.
If you just want to have the whole class with different types (not just the Init), e.g. also have int *a; int b,c; then template classes are the other trick you don't know yet.
template <typename ANYTYPE> class InitLine
{
private:
ANYTYPE *a;
ANYTYPE b, c;
public:
void InitLine(ANYTYPE *inita, ANYTYPE initc);
void Init(ANYTYPE *a, ANYTYPE c);
};
template <typename ANYTYPE> void Initline<ANYTYPE>::Init(ANYTYPE *a, ANYTYPE c)
{
for (int b=0; b<c; b++)
*(a+c)=0;
}
... main()
{
Initline<int> iline; // initline class based on type int (ANYTYPE -> int)
int line[20];
Initline<char> cline; // initline class based on type char (ANYTYPE -> char)
char somechars[30];
iline.Init(line, 20);
cline.Init(somechars, 30);
in c++ ..
first of all I need to make a constructor of class Date d() that creates the current date.. what should i do?
after that i have a problem with this program:
class Noleggio
{
public:
//Noleggio(unsigned f, unsigned n, unsigned c) : inizio() { film = f; copia = n; cliente = c; restituito = false; }
bool restituito;
unsigned addebito;
//unsigned film, copia, cliente;
Data inizio;
Data restituzione;
CopiaFilm* copia;
Film* film;
Cliente* cliente;
};
class VideoNoleggio
{
public:
VideoNoleggio (string n) : nome(n) {}
void InserisciFilm (Film* f);
void InserisciCliente (Cliente* c);
void CreaCopiaFilm (string s, Film* f);
void NoleggioCopia (unsigned n, Film* f, Cliente* c);
void RestituzioneCopia (unsigned n, Film* f, unsigned t);
int CercaFilm (Film* f) const;
int CercaCliente (Cliente* c) const;
int CercaUltimaCopia(Film* f) const;
int CercaNoleggio (unsigned n, Film* f) const;
string Nome() const { return nome; }
unsigned NumeroFilm() const { return film.size(); }
unsigned NumeroNoleggi() const { return noleggi.size(); }
Film* QualeFilm (unsigned i) const { return noleggi[i].film; }
string QualeTitolo (unsigned i) const { return film[i]->Titolo(); }
private:
string nome;
vector<Noleggio> noleggi;
vector<CopiaFilm> copie;
vector<Film*> film;
vector<Cliente*> clienti;
};
in function
void VideoNoleggio::RestituzioneCopia (unsigned n, Film* f, unsigned t)
{
int i = CercaUltimaCopia(f);
assert (copie[i].numero >= n );
assert ( !(noleggi[i].restituito) );
Data d();
int j = CercaNoleggio(n,f);
assert ( d >= noleggi[j].inizio );
noleggi[j].restituzione = d;
noleggi[j].restituito = true;
noleggi[j].addebito = t*( d - noleggi[j].inizio + 1 );
// clienti[noleggi[j]->cliente]->Prelievo(noleggi[j]->addebito);
}
the compiler returns an error here assert ( d >= noleggi[j].inizio ) it seems to don't like noleggi[j].inizio as a good parameter... (cause if i try d >= d it works---> it's not an operator overloading problem i guess)
in data.h friend bool operator >= (const Data& d1, const Data& d2);
any suggestion?
The problem is the line
Data d();
This is interpreted as a function declaration (i.e. a function called d, taking no arguments and returning a Data).
Change it to
Data d;
or, if it's a POD structure and you want it value-initialised
Data d = Data();
As for how to implement the constructor, that will depend on your environment; there is no standard C++ date/time library. The most portable way is probably to use Boost.Date_Time, as daramarak suggests, but I've not used it myself so I can't do more than point you at the documentation. On Posix systems, you have the time() function to return the number of seconds since a defined date, and ctime() and related functions to break it down into years, months, etc. Windows probably has something similar, but I don't know about that.
My suggestion would be to use boosts date time library
Data d; is the declaration of a Data object called d.
Data d(); declares a function d() which returns a Data.
See C++ FAQ 10.2.