ambiguous reference error for member variable 'name' - c++

I have declared a variable name within my people class which is producing an ambiguity error. I tried renaming the name variable, avoided using using namespace std, imported the required libraries, replaced character array with string type but it throws same error all the time. I referred to other posts on Stack Overflow but I could not find the solution.
#include <iostream>
#include <cstdlib>
#include <cstring>
class people{
public:
char name[20];
};
class staff : public people {
public:
int i = 3;
};
class manager : public people {
public:
int j = 8;
};
class lecturer : public manager, public staff {
public:
void set(char* a) {
strcpy(name, a);
}
void get(){
std::cout << "Lecturer name: " << name << std::endl << "Number of managers: " << j << std::endl << "Number of staff: " << i << std::endl;
}
};
int main() {
lecturer ob;
ob.i = 1;
ob.j = 6;
ob.set("aaa bbb");
ob.get();
return 0;
}
and the error message is
main.cpp:24:16: error: reference to ‘name’ is ambiguous
strcpy(name, a);

The compiler doesn't know which member 'name' should use in the strcpy function since lecturer inherits from 2 classes which are manager and staff (both have member 'name'), so to tell the compiler who's name should use, to assign manager's name, you can use:
strcpy(manager::name, a);
and for staff's name:
strcpy(staff::name, a);

Related

constructor's problem to initialize pointer data member

I encountered a problem while initializing a pointer data member i.e int* apex; inside a constructor
having parameter as int i = 0; as *apex = i;
but unfortunately nothing is executed after compiler strikes this line.
#include <iostream>
using namespace std;
class base{
int *apex;
public:
explicit base(int i = 0){
cout << "this does executes" << endl;
*apex = i; // <<<<<--- problem???
cout << "this doesnt executes" << endl;
}
};
int main(void){
base test_object(7);
cout << "this also doesnt executes";
}
// I know how to avoid this but i want to know what
// exactly the problem is associated with *apex = i;
THANKS IN ADVANCE
note-no error is generated
What you wrote is equivalent to:
int *apex;
*apex = 42;
which is undefined behavior (UB), which includes that the compiler might just include code to stop execution or to start playing the song Never Gonna Give You Up by Rick Astley.
Even
int *apex = nullptr;
*apex = 42;
would be UB because the int* pointer has to point to a valid int when dereferencing via *
Just write
class base{
int apex{};
public:
explicit base(int i) : apex(i){}
};
And be done for
I got it. Trust me I am ashamed of myself after this silly doubt.
#include <iostream>
using namespace std;
class base{
int *apex;
public:
explicit base(int i = 0){
apex = new int;
// this is what i was supposed to do
*apex = i;
}
};
int main(void){
base test_object(7);
}
Your pointer points to invalid address you didn't initialize it
This will fix what you have asked to be done.
using namespace std;
class base{
int *apex{nullptr};
public:
explicit base(int& i ): apex{&i} {
cout << "this does executes" << endl;
cout << "this doesnt executes" << endl;
}
};
int main(void){
int a = 7
base test_object(a);
cout << "this also doesnt executes";
}
Make sure something (int) given to ctor has longer lifetime than an instance.

Weird behavior with OOP and string pointers

Here's my code:
#include <iostream>
#include <string>
class Human
{
public:
std::string * name = new std::string();
void introduce();
};
void Human::introduce()
{
std::cout << "Hello, my name is " << Human::name << std::endl;
}
int main()
{
Human * martha;
martha->name = new std::string("Martha");
martha->introduce();
return 0;
}
Well, it's supposed to print a message out like:
"Hello, my name is Martha" but it doesn't print neither the "Hello, my name is" string or the "Martha" name. Why does it occur?
The fix is simple and is to completely remove all pointers; see the code below. There are a number of issues with your code that I could address in detail, including memory leaks, uninitialized variables, and general misuse of pointers, but it seems that you're possibly coming from a different language background and should spend time learning good practice and the important semantics and idioms in modern C++ from a good C++ book.
#include <iostream>
#include <string>
class Human
{
public:
std::string name;
void introduce();
};
void Human::introduce()
{
std::cout << "Hello, my name is " << name << std::endl;
}
int main()
{
Human martha;
martha.name = "Martha";
martha.introduce();
return 0;
}
Few modifications are required to the code.
Updated code along with the comments to the change made are included below.
#include <iostream>
#include <string>
class Human
{
public:
//Removed pointer to a string
//Cannot have an instantiation inside class declaration
//std::string * name = new std::string();
//Instead have a string member variable
std::string name;
void introduce();
};
void Human::introduce()
{
//Human::name not required this is a member function
//of the same class
std::cout << "Hello, my name is " << name << std::endl;
}
int main()
{
Human *martha = new Human();
//Assign a constant string to string member variable
martha->name = "Martha";
martha->introduce();
return 0;
}
As suggested by #alter igel - The Definitive C++ Book Guide and List would be a good place to start.
#include <iostream>
#include <string>
class Human {
public:
void Human(std::string* n) { name = n; }
void introduce();
private:
std::string* name;
};
void Human::introduce() {
std::cout << "Hello, my name is " << name << std::endl;
}
int main() {
Human* martha = new Human(new std:string("Martha"));
martha->introduce();
return 0;
}
Try that. The difference is that you don't initialise the variable in the class definition, and you initialise the name with the constructor. You can split the method definition out into it's own section, but it's only one line and is fine being inside the class definition.

Static Functions and class variables?

I have broken down my issue into a small simple program.
I have a class myclass I have created in a separate .cpp file "classes.cpp" and declared in the header file "classes.h". myclass contains a variable a of which is initialized when instantiated. This makes variable a = 5.
My overall goal is to create a class in a separate .cpp file declared in a .h file which I can create multiple instances of in my main() program. The problem I am having is this.
In my main() function I create an instance of myclass called first.
my main program shows the variable a is set to the number 5.
If I want to change that number using a static function (and it has to be a static function as this relates to something much bigger in another program I am writing). I call the static function directly and in that static_function I create an instance of myclass and call the non_static_function because static functions have no implicit 'this' connecting them to an object.
In my non_static_function I change the value to the number 8. The problem is that the value of variable 'a' in 'first' remains at 5 when I want it to be 8. I need to change the value using first->static_function(8) and not by first->a = 8. . How can I do this?
Code below:
**main.cpp**
#include <iostream>
#include "classes.h"
using namespace std;
int main()
{
myclass *first = new myclass();
cout << "Myclass variable a is = " << first->a << endl;
first->static_function(8); // trying to change myclass variable 'a' to 8.
cout << "But" << endl;
cout << "the actual value of a is still: " << first->a << endl;
}
**classes.h**
#ifndef CLASSES_H_INCLUDED
#define CLASSES_H_INCLUDED
class myclass
{
public:
int a;
myclass();
void non_static_function(int x);
static void static_function(int x);
};
#endif // CLASSES_H_INCLUDED
**classes.cpp**
#include <iostream>
#include <cstdlib>
#include "classes.h"
using namespace std;
myclass::myclass()
{
a = 5;
}
void myclass::non_static_function(int x)
{
a = x;
cout << "The value for variable 'a' was 5 but is now: " << a << endl;
}
void myclass::static_function(int x)
{
myclass *p = new myclass();
p->non_static_function(x);
}
If you want every instance of myclass to have its own a and you want to call a static function to change it then you need to pass the instance you want changed to the static function. A static function can only modify static members of a class or the members of an instance that is inside its scope. Non static member functions can change any variable that is a member of the class.
class Foo
{
private:
int bar;
public:
static void static_function(int value, Foo & foo) { foo.bar = value; }
void non_static_function(int value) { bar = value; }
};
int main()
{
Foo foo;
Foo::static_function(8, foo);
// now bar will have the value of 8
foo.non_static_function(20);
// now bar will have the value of 20
}
I have finally found a way to deal with this small problem. Above the 'myclass' definition in classes.cpp I declare a 'myclass' variable
myclass *tgt; . Then in my constructor for 'myclass' I just allocate the instantiated object to a my global myclass variable of which I can access from the myclass definition tgt = this; Now I can use tgt in my static function to call the non_static_function in my 'myclass' definition and it all works perfectly.
NathanOliver, you are correct in saying that I need a class instance but the way I have done it here suits my needs. Passing the instance of myclass is certainly another way of doing this but it would require a global function above my 'myclass' definition.
Thanks for the help.
**main.cpp**
#include <iostream>
#include "classes.h"
using namespace std;
int main()
{
myclass *first = new myclass();
cout << "Myclass variable a is = " << first->a << endl;
first->non_static_function(8); // trying to change myclass variable 'a' to 8.
cout << "But" << endl;
cout << "The actual value of a is still: " << first->a << endl;
myclass *second = new myclass();
cout << "For the 'second' class the variable a is: " << second->a << endl;
second->non_static_function(23);
cout << "After calling the static function from 'second' the value of a is: " << second->a << endl;
cout << "And first->a is still: " << first->a << endl;
}
**classes.h**
#ifndef CLASSES_H_INCLUDED
#define CLASSES_H_INCLUDED
class myclass
{
public:
int a;
myclass();
void non_static_function(int x);
static void static_function(int x);
};
#endif // CLASSES_H_INCLUDED
**classes.cpp**
#include <iostream>
#include <cstdlib>
#include "classes.h"
using namespace std;
myclass *tgt; // *Add a global myclass variable above the myclass
definition*
myclass::myclass()
{
tgt = this; // *In the constructor allocate the instantiated class
//from main() to "tgt" .*
a = 5;
}
void myclass::non_static_function(int x)
{
a = x;
// Now see that the value of a is changed.
cout << "The value for variable 'a' was 5 but is now: "<< this->a << endl;
}
void myclass::static_function(int x)
{
tgt->non_static_function(x);
}

C++ - friend functions

I am trying to make a simple friend function work, but not in just one source file. I seem to get an error and I can't seem to find an answer why.
Please have a look at my code:
----------classOne.h--------------
#ifndef CLASSONE_H_
#define CLASSONE_H_
using namespace std;
class ClassOne {
private:
int m_a;
int m_b;
public:
ClassOne(int a, int b);
void printValuesOne();
friend void ClassTwo::twoPrintsOne();
};
-
----------classOne.cpp------------
#include <iostream>
#include "classOne.h"
using namespace std;
ClassOne::ClassOne(int a, int b) {
m_a = a;
m_b = b;
}
void ClassOne::printValuesOne() {
cout << "m_a: " << m_a << " " << "m_b: " << m_b << endl;
}
.
----------classTwo.h-------------
#ifndef CLASSTWO_H_
#define CLASSTWO_H_
using namespace std;
class ClassTwo {
private:
int m_c;
int m_d;
public:
ClassTwo(int c, int d);
void printValuesTwo();
twoPrintsOne();
};
#endif
-
---------classTwo.cpp-----------
#include <iostream>
#include "classTwo.h"
using namespace std;
ClassTwo::ClassTwo(int c, int d) {
m_c = c;
`enter code here`m_d = d;
}
void ClassTwo::printValuesTwo() {
cout << "m_c: " << m_c << " " << "m_d: " << m_d << endl;
}
void twoPrintsOne() {
cout << "ClassTwo: " << m_a: " << m_a << " " << "m_b: " << m_b << endl;
}
Basically ClassOne and ClassTwo are the same sort of thing, but only one of ClassTwo's method has access to all of ClassOne's members, so ClassTwo can print ClassOne's member variables. However, when I try to compile the whole program (I haven't provided the main method here), I get this error an error:
classOne.h:19:15: error: ‘ClassTwo’ has not been declared
friend void ClassTwo::twoPrintsOne();
^
Can someone help and explain?
ClassOne doesn't know about ClassTwo, therefore it cannot befriend with any of its methods. You have to add:
#include "classTwo.h"
on top of your classOne.h.
You are getting confused with what "friend" is supposed to do.
"friending" ClassTwo will allow ClassTwo to access the private members of ClassOne as if they were public.
It will not link those members between the two classes in any way.
You could have ClassTwo inherit from ClassOne, or add a ClassOne member in ClassTwo

need help with object oriented program in Visual C++

guys, I have the following code, but I'm getting error at compiling time... the error is at the end. Thanks
1st Class is "Person"
#ifndef PERSON_H//protecting .h files
#define PERSON_H//protecting .h files
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
Person();
Person(string first, string last)
{
firstName = first;
lastName = last;
}
virtual void setName(string first, string last)
{
firstName = first;
lastName = last;
}
virtual void setWeightAge(int w, int a)
{
weight = w;
age = a;
}
virtual string getFirstName()
{
return firstName;
}
virtual string getLastName()
{
return lastName;
}
virtual int getWeight()
{
return weight;
}
virtual int getAge()
{
return age;
}
virtual void printPerson()
{
cout << "Name: " << firstName << " " << lastName << endl;
cout << "Age: " << age << endl;
cout << "Weight: " << weight << endl;
}
protected:
string firstName, lastName;
int weight, age;
};
#endif
2nd Class is "Student"
#ifndef STUDENT_H//protecting .h files
#define STUDENT_H//protecting .h files
#include <iostream>
#include <string>
#include "Person.h"
using namespace std;
class Student : public Person
{
public:
Student();
Student(Person s)
{
sStudent = s;
}
virtual void setGPA(double g)
{
gpa = g;
}
virtual void setSchedule(string c, string t, string d)
{
stClass = c;
time = time;
days = d;
}
virtual void setGrade(char g)
{
grade = g;
}
virtual double getGPA()
{
if (grade == 'a') { gpa = 4.0; }
if (grade == 'b') { gpa = 3.0; }
if (grade == 'c') { gpa = 2.0; }
else gpa = 0;
return gpa;
}
virtual char getGrade()
{
return grade;
}
virtual void printSchedule()
{
cout << "Class | Days | Time " << endl;
cout << stClass << " | " << days << " | " << time << endl;
}
protected:
string stClass, time, days;
char grade;
double gpa;
Person sStudent;
};
#endif
and Main()
#include <iostream>
#include "Student.h"
using namespace std;
int main()
{
//creating a person
Person john("John", "Smith");
john.setWeightAge(180, 39);
john.printPerson();
//making john a student
Student johnStdntMath(john);
johnStdntMath.setSchedule("Math", "7:45", "M, W");
johnStdntMath.setGrade('b');
johnStdntMath.printPerson();
johnStdntMath.printSchedule();
system("pause");
return 0;
errors:
1>------ Build started: Project: Person, Configuration: Debug Win32 ------
1> main.cpp
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall Person::Person(void)" (??0Person##QAE#XZ) referenced in function "public: __thiscall Student::Student(class Person)" (??0Student##QAE#VPerson###Z)
1>c:\users\jorge\documents\visual studio 2010\Projects\Person\Debug\Person.exe : fatal error LNK1120: 1 unresolved externals
}
I suggest you double check your is-A and has-A relationships.
Writing Student : public Person says that a Student is-A Person. But later, you have a member variable sStudent of type Person, which says a Student has-A Person, and I'm guessing is not what you really want.
Check out the answers to this question: Inheritance vs. Aggregation for better explanations.
Listen to your linker, it's just as it says: In constructor Student::Student(Person) you're referring to constructor Person::Person(), but you didn't define Person::Person(), not in a way the linker can see when it does its thing with the Student constructor.
Technically, because you are filling in sStudent in the Student constructor's body the compiler first default-initializes the Person object sStudent, and then assigns to it s, the Person parameter of the constructor. If you'd use the initializer list then the Person member wouldn't be default-initialized and then assigned to but rather copy-constructed right away:
Student(const Person& s) : sStudent(s) { }
But the question remains: Why are you publicly declaring a default constructor in Person and not define it?
Also, you have a leak in Student. The string and Person members of Student won't clean up because when a Student object destructs its destructor won't be called. The Person destructor will be called, but not the Student destructor, and the reason being that the destructor of Person is non-virtual.
One more thing: It's a bad idea in object-oriented design in general and C++ in particular to use inheritance for reuse. The reason is that this very often leads to a violation of the LSP. It can also bear a (not major but nonetheless) performance overhead for introducing a virtual table. But it's the correctness that suffers that matters when you pick inheritance when you should really be using delegation.
You are accessing the no argument constructor for Person when you create the johnStdntMath instance. You need to either
Implement Person::Person() or ...
Change Student::Student(Person s) to Student::Student(Person const& s)
There are some other problems in your code as well. Student is-a Person so there is no need for the Student class to have a Person member variable - it shares the instance variables of its base class by virtue of inheritance. In other words, Student extends Person so your program could be written:
int main() {
Student johnStdntMath;
johnStdntMath.setName("John", "Smith")
johnStdntMath.setWeightAge(180, 39);
johnStdntMath.setSchedule("Math", "7:45", "M, W");
johnStdntMath.setGrade('b');
johnStdntMath.printPerson();
johnStdntMath.printSchedule();
return 0;
}
I would also avoid the using namespace std; statement anywhere and especially in a header file. For example, your Student class contains a member variable named time. This will conflict with the std::time_t std::time(std::time_t*) function defined in <ctime> if that header is included before "student.h".
You haven't implement the default constructor Person(),you can write it like this:
Person():weight(0)
,age(0){};
If you just want to complier it, this is enough;
Here are some tips below:
1.Check your mind, does class Student really need a Person member. If you really need it, Student(Person) may add an explicit symbol:
explicit Student(const Person& s) : sStudent(s) {...};
2.In Person.h
protected:
string firstName, lastName;
int weight, age;
the protected may be private?