C++ object not working with dot operator - c++

Hello I am working on a C++ program and I am just starting out by creating some sample objects out of the class that I created. I am creating the object but for some reason the dot operator is not working with the object
This is the object call
Card testcard(Suit hearts, Value six);
This is the constructor
Card::Card(Suit suit, Value facevalue)
{
Card::suit=suit;
Card::faceValue=facevalue;
};
However the dot operator is not working, as if the object is not really there
I am controlling most of the program in seperate parts so there are many instances of header files which is where the card class is located, I am not sure if that is part of the problem

From within an instance method, you can't use a dot to access the instance.
Try this-> instead:
Card::Card(Suit suit, Value facevalue)
{
this->suit=suit;
this->faceValue=facevalue;
};
Alternately, you can use an initializer list:
Card::Card(Suit suit, Value facevalue) : suit(suit), faceValue(facevalue)
{ }

Assuming the class looks something like:
class Card {
public:
Card (Suit argSuit, Value argFaceValue);
private:
Suit m_Suit;
Value m_FaceValue;
};
The constructor would look like this. Since the members of the class are available to the objects created from the class you do not need to do anything special to access them. The members of the class are within scope and are visible. You just need to make sure that the argument list of the function uses different symbols or names than the class/object members.
Card::Card(Suit argSuit, Value argFaceValue)
{
m_Suit = argSuit;
m_FaceValue = argFaceValue;
}

This is the object call
Card testcard(Suit hearts, Value six);
No, that's a function declaration. Naturally using the member access operator (.) on the name of a function doesn't work, the function has its own type which doesn't have members.
To declare an automatic variable (creating a new object instance), don't repeat parameter types. Just say:
Card testcard(hearts, six);

I think some of your naming conventions are causing some confusion for you. As pointed out above, you are running into a problem of context with the suit and facevalue arguments passed to the constructor. This means that in the context of the constructor method, suit really means the suit that is passed in as an argument, over the suit that is a member variable of the class Card. People generally use a naming convention to help avoid this confusion, such as putting an m_ in front of each data member for the class, such that suit would become m_suit. You can use whatever you like, but that way someone else code would know right away that m_suit was a data member.
Another point is that you can, and probably should, initialize the data member for a class prior to the code for the constructor is executed. This is called the "initialization list" and would be done as follows (assuming you changed over to the naming convention above).
Card::Card (Suit suit, Value facevalue)
: m_suit (suit), m_facevalue (facevalue)
{
// no code needs to go here
}
For efficiency reasons it is a good idea to get in this habit. Further, using the this pointer is generally not a good idea in a constructor. It's not illegal, but can get you into trouble.
As far as the dot operator not working, it wasn't clear from your question exactly where you were using the dot operator. If you are referring to the :: syntax above, that isn't really an operator, it is part of the C++ syntax indicating that you are dereferencing the class. That syntax would work if you had declared the suit and facevalue data members as static, but that is not what you wanted to do.
You mention that you are declaring the Card class in multiple header files -- that too is bad.

Related

No matching function for call to...?

I'm getting an error for what I assume is declaring the incorrect type, but I'm not sure where the issue is or what I need to fix. I'm using two files.
Please tell me if I haven't given enough info, I'm still a newbie. I'd really appreciate the help.
I appreciate you can't change the input for the test, but whoever wrote the test needs to be told it's a bad test.
Data should be initialized through a constructor.
Data members (address and price) should be declared as private not public.
Whoever wrote the test is requiring you to write a bad C++ class.
That said, you can conform with this bad test by adding to the .h file:
HousePrice();
and to the .cpp file
HousePrice::HousePrice():address(""),price(0){}
Thereby giving it the expected default constructor.
Change it to
#include "zillow.h"
HousePrice hp ("1600 Pen. Ave",1561.53);
ASSERT_EQ(hp.price, 1561.53);
Previously you were trying to create your HousePrice object with no constructor parameters, but the only constructor you've written takes address and price.
The error is here:
HousePrice hp;
When you create an object of a class like that, the default constructor of the class is invoked implicitly. But your class definition does not have a default constructor.
Solution:
Since you are not allowed to change the code at the caller's part, you should modify your class definition such that it contains a default constructor. Then it is upto you to decide the initial values or simply leave it empty.
For example:
Add HousePrice() inside the class definition in zillow.h
Add the following into zillow.cpp
HousePrice::HousePrice()
{
address = "";
price = 0.0;
}
The answer is in the error message. You are trying to default-construct an object of HousePrice type, but HousePrice does not have a default constructor.
Add a default constructor (a constructor with no parameters)
Side note: there is no point in having getter or setter functions in this example. Your data members are public and you don't have any constraints on them

C++ construct asks for a struct that is not defined in .h

I have to do some changes in a project so I have to change some classes. This code was made by another person and I found a really weird problem doing my task (or at least trying until this wild mushroom appeared )
I have the next ClassA.cpp and I want to remove the m_ElemVar(enumType):
CClassA::CClassA(): m_iIntVariable(0), m_fFloatVar(0.0f), m_ElemVar(enumType1)
{
// more variables initizalized there
otherVariable = value;
...
}
the .h :
#include "CMyElement"
class CClassA
{
public:
CClassA();
virtual ~CClassA();
private:
CMyElement m_ElemVar; // THIS is the var
int m_iIntVariable;
float m_fFloatVar;
...
}
So the thing is that I don't want the m_ElemVar(enumType1) there because I will initialize it in another place, BUT if I remove it, when I build the class or the project it says:
error: no matching function for call to ‘CMyElemnt::CMyElemnt()
candidates are CMyElemnt::CMyElemnt(enumTypeName)
while if I remove the m_fFloarVar for example it doesn't complains.... That confuses me a lot because as you can see in the .h there is nothing declared so I understand that this constructor should not expect anything.
I've clean and build it again, and also searched into google but nothing found so any help would be very appreciated. Thank you so much
Looks like CMyElemnt does not have a parameterless constructor so you have to call one that takes the enum. Maybe you could reassign it later if you cannot change its interface.
The issue you are having is all objects of a class must be constructed in order for the class to be constructed. If you don't construct one of the member explicitly then the compiler will do it for you implicitly using the default constructor. Since CMyElemnt does not have a default constructor you will get an error. The reason not initializing m_fFloatVar works is it is a float and the compiler can default construct a float.
To look at a different way anything you can write as
some_type some_name;
Is default constructable. If you have do include parameters like:
some_type some_name(some_variables)
Then it is not default constructable and you need to initialize it yourself.

Why can I not initialize non-static member outside class declaration?

class ClassObject {
public:
ClassObject();
virtual ~ClassObject();
private:
int x;
};
int ClassObject::x=10;
Why does it fail to compile?
I think that if static members can be initialized this way, then it should also be possible for non-static ones.
Static members are special. They have a memory allocated to them as soon as the class is defined. And no matter how many objects of that class we create all those objects refer to the same piece of memory.
This is not the case with non static members. Unless you create an object of that particular class, the non static members are not allocated any memory and hence trying to instantiate them in the above way leads to compiler error.
I'm guessing you mean declaring the value used to initialise x for any new ClassObject, i.e. you mean that as equivalent to
ClassObject() : x(10) { }
The problem with your syntax is that the compiler needs to generate code to do that initialisation in every ClassObject constructor; i.e. it can only work if the int ClassObject::x = 10; initialisation is available in the compilation unit that defines all constructors, and any compilation units that generate one implicitly. And the only way to guarantee that is if the value is set inside the class definition, not outside it as you have. (However this is now possible in C++11 - see the link in tacp's comment.)
If we did want to make your syntax work, then we'd need to store the declared value as a hidden static somewhere in a way that any constructors would pick it up and know to use it as the initial value for x. However this static may or may not exist, and the only point we can know that for a constructor in a different compilation unit is at link time. Hence we either generate extra, redundant code to initialise x from this hidden static if it exists (or redundant data) or we mandate link-time-code-generation to solve this, which puts a large burden on the compiler developer. It is possible, yes, but it's simpler all around if this isn't allowed.

Instance-level encapsulation with C++

I have a two-part question. First, I understand that C++ provides only class-level data encapsulation, meaning that all objects of the same class have access to one another's private members. I understand the reason for this, but have found some links (i.e. http://www.programmerinterview.com/index.php/c-cplusplus/whats-the-difference-between-a-class-variable-and-an-instance-variable/) which appear to contradict this point, suggesting that I could do the following:
class testclass {
private:
// Below would be an instance-level variable, and new memory for it is set aside
// in each object I create of class testclass
int x;
// Below would be a class-level variable, memory is set aside only once no matter
// how many objects of the same class
static int y;
}
What I would like to do is actually make this work, i.e., I would like to define a variable in a class which is private in each instantiation (this is my second question). Since the code snippet above does not appear to achieve this, is there a work around I can use to create data that is private to individual objects? Thank you!
EDIT:
It's true that I'm still learning OO basics. I'll use the ubiquitous car example to show what I'm trying to do, which I'm sure must be a common thing to try. I'd welcome any suggestions for how to rethink it:
class car {
private:
int mileage;
public:
car(int); // Constructor
void odometer();
};
car::car(int m) {
mileage = m;
}
void car::odometer() {
return mileage;
}
int main(void) {
car ford(10000), honda(20000);
cout<<ford.odometer(); //Returns 20000, since honda constructor overwrites private variable 'mileage'
}
Is there any way to get the odometer() method to return the mileage of either the ford or honda, depending on what I want?
Priviledge (public, private, protected) only applies to names. Only during the time when a name is resolved will the compiler apply permissions. Once compiled, all such information is gone.
In your example above, all uses of the names x and y within a scope that resolves to THOSE variables will be private to your class. Only functions declared in your class, be they static or not, will be able to access those variables by name.
All bets are off however if you give out the variable to other objects that can then refer to the variable by other names which have other permissions.
I'm not sure what you're asking with reference to "in each instantiation". AFAIK, there is no native way to make a variable private such that only that instance can access it. In all cases, instances can access each other's private parts.
There's some ways you could get around this I suppose. First is to templatize your class and give each instance a different type. You could do this with an integer template parameter or something. This could make life annoying though as you try to work with these types as the same kind of thing. You'd have to virtualize and have an abstract base class or something.
Currently that's the only method I can think of. All others depend on calling entities playing nice.
Generally speaking it's rare that you'd want to protect members from other instances. The usual case of the same type being passed to the same type is during copy and assignment, where you basically need all knowledge about the source to correctly copy. My bet is that you need to rethink what you're trying to do, whatever that is.

Strange "type class::method() : stuff " syntax C++

While reading some stuff on the pImpl idiom I found something like this:
MyClass::MyClass() : pimpl_( new MyClassImp() )
First: What does it mean?
Second: What is the syntax?
Sorry for being such a noob.
This defines the constructor for MyClass.
The syntax is that of a constructor definition with an initialization list (I assume there is a set of braces following this that define the body of the constructor).
The member pimpl_ of MyClass is being initialized as a pointer to a new object of type MyClassImp. It's almost the same as the following:
MyClass::MyClass()
{
pimpl_ = new MyClassImp();
}
However, it is preferable to use the initialization list for initializing class members wherever possible; see the C++ FAQ Lite entry linked above.
It's an initialization list.
It allow you to set the values of member and base class constructor before the constructor code is called.
You should use it to initialize the values of your class instance.
In addition to being a constructor with an initialiser list as others have already explained, it's also using the private implementation pattern.
C++ requires the class declaration to include all the public and private members of the class. This can result in you having to expose implementation details that you don't want to, and to making your implementation part of your API/ABI. It can also significantly increase compile times due to additional #includes in the public headers to support the private member variables.
Making a second class with the actual implementation and just exposing the functional API makes this much cleaner, but at the cost of an additional layer of indirection.
C generally handles this by having a pointer to an opaque object which the library creates and destroys for you.