Expected primary expression before '.' - c++

#include <iostream>
using std::cout;
using std::endl;
class square {
public:
double length, width;
square(double length, double width);
square();
~square();
double perimeter();
};
double square::perimeter() {
return 2*square.length + 2*square.width;
}
int main() {
square sq(4.0, 4.0);
cout << sq.perimeter() << endl;
return 0;
}
I'm trying to write a simple class program. I am getting the error
in member function 'double square::perimeter()';
.cpp:21: error: expected primary-expression before '.' token
.cpp:21: error: expected primary-expression before '.' token
Does this mean I have to use 2*square::length + 2*square::width?

square is a type, not an object; instead of
return 2*square.length + 2*square.width;
do
return 2*length + 2*width;
(which is implicitly the same as:
return 2*this->length + 2*this->width;
which you may, or please may not, prefer for clarity).
2*square::length + 2*square::width would be valid syntax if length and width were
static members of square, or
members of some base class square, or
objects in some namespace square

Yes, the accurate form would be:
return 2*square::length + 2*square::width;
since square is a type, not an object.
In this context, it's the same as:
return 2*this->square::length + 2*this->square::width;
However, since it's the same object and the same type, you can just write:
return 2*this->length + 2*this->width;
or, most simply:
return 2*length + 2*width;

Simply use
double square::perimeter() {
return 2 * length + 2 * width;
}

double square::perimeter() {
return 2*square.length + 2*square.width;
}
You need to say square::perimeter() because you are defining a method of the square class itself. It may seem like you want to define it on a specific object, but you want it to be available to all instances of square, so you need to define it on a specific one.
The instance variables length and width on the other hand, pertain to a specific instance of a class and NOT the entire class itself (otherwise you would declare them as static). This means that you can just refer to them directly instead of going through the class itself, and the compiler will know what variables you're talking about. This is because width and length are defined in the same scope as the method, so you don't need to give it special directions with :: to tell it where to find what its looking for. Hence:
double square::perimeter() {
return 2 * length + 2 * width; //will refer to the instance variables automatically
}

to access instance variables, just name them:
double square::perimeter() {
return 2*length + 2*width;
}

double square::perimeter() {
return 2*square.length + 2*square.width;
}
what is the square in this function? square is a class. you use the . operator to acces members from objects. like sq.somefun();
so you perimeter function should be:
double square::perimeter() {
return (2*(length + width));
}
But isnt the length and width of square equal?

Related

Does this coding style belong to an older version of C++?

I come across this code in my older books. I tried to run it in Visual Studio 2019, but it gave me an error:
volume function does not take zero arguments
Is this because the code is old, or the code is wrong?
#include<iostream>
using namespace std;
class Cylinder
{
private:
const double pi = 3.14;
double r, h;
public:
void ro(double radius) {
r = radius;
}
void ho(double height) {
h = height;
}
double volume(double r, double h)
{
return pi * r * r * h;
}
};
int main()
{
Cylinder s;
s.ro(1);
s.ho(2);
cout << s.volume();
return 0;
}
The code is wrong. The volume function is declared to take two double arguments and the C++ compiler expects it to be called that way.
I'm not aware of any C++ compiler of any age that would accept that code.
It looks like maybe the function is trying to use the member variables r and h, in which case you should probably remove the parameters from the declaration of volume.
The code is wrong.
When calling a function, you must pass in as many values as there are parameters declared. You can't skip parameters, unless they are declared with default values, which is not the case here.
Given the way main() is using Cylinder in this example, the 2 input parameters need to be removed completely, since they are shadowing the r and h class members that are being set by the ro() and ho() methods.
double volume()
{
return pi * r * r * h;
}
Now the call to cout << s.volume(); will work as expected.
I believe the code is wrong.
If you had default argument on the method.
E.g something like this:
double volume(double r = 0, double h = 0)
{
return pi * r * r * h;
}
It would work when you call it without parameters.

a pointer to function within a operator

for homework, I need to write a program in cpp with a class composed of an array of pointer to function and operators. I need to create an operator + so as when in the main, this would happen:
int main()
{
int SIZE = 5;
ptrF* arrPtrF = new ptrF[SIZE];
arrPtrF[0] = add;
arrPtrF[1] = sub;
arrPtrF[2] = mult;
arrPtrF[3] = div1;
arrPtrF[4] = pow;
Delegate D1(arrPtrF, SIZE)
cout<< D1[0](6, 7) + D1[0](1, 2)<<endl;
}
the outcome is 15
I am finding difficulty with writing the operator+ ( which in this case need to take take a object parameter)
at first i tried this:
Delegate Delegate:: operator + (const Delegate& b)
{
Delegate tmp;
tmp.m_ptrF[i] = m_ptrF[i] + b.m_ptrF[i];
return tmp;
}
but it gave me an error about the i and b.m_ptrF->initialized i and something about an enum type.
then i tried this:
int Delegate:: operator + (const Delegate& b)
{
int tmp;
int i, x,y;
tmp = m_ptrF[i](x, y) + b.m_ptrF[i](x, y);
return tmp;
}
but it gives me an error->initialized x,y,i knowing that i is index and x,y the parameters of the pointer to function.
what can i do to make it work?
It looks like D1[0](6, 7) is supposed to perform 6 + 7 returning an int and D1[0](1, 2) is supposed to perform 1 + 2 also returning an int. So the addition in D1[0](6, 7) + D1[0](1, 2) is just a regular int addition.
So in other words you are not supposed to be overloading Delegate::operator+ instead you are supposed to writing something like this
XXX Delegate::operator[](int i) const
{
...
}
where XXX is a function like type that will perform the addition on the later parameters.
So XXX will be something like
class XXX
{
public:
int operator()(int x, int y) const
{
...
}
...
};
But XXX will have to perform addition, or substraction or whatever, as appropriate.
So the expression D1[0](6, 7) becomes temp(6,7) where temp is an object of the XXX type above.
At least that's my best interpretation. It's clear that you have misunderstood your requirements.

variable has initializer but incomplete type C++

I am new to C++. I have this code to create a struct, to show the usage of mutable keyword in C++.
#include <iostream>
using namespace std;
int main()
{
struct
{
mutable double radius;
double PI = 3.142;
double getArea()
{
return (PI * radius * radius);
}
} circle;
const struct circle c1 = {2.0};
circle.radius = 7;
cout << "Area is " << circle.getArea() << endl;
return 0;
}
But I get the following error message when compiling:
error: variable const main()::circle c1 has initializer but incomplete type
Error is at c1 in the line const struct circle c1 = {2.0};. Can anyone point me out the error here.
You don't define a structure named circle, you define a variable named circle. This variable can not be used as a type.
You should do e.g. struct circle { ... }; to define the structure as a type. Then you could do
const circle c1 = { 2.0 };
c1.radius = 7;
std::cout << c1.getArea() << '\n';
There are a few other problems, most notable you don't declare the getArea function as const which means you can't call it on const objects.
When you put the name circle after the right brace at the end of the struct definition, you're declaring a variable.
Put it at the start, after the word struct, to declare a type.
I.e.
struct circle
{
// ...
};
In other news:
You'll need to declare getArea() as const to be able to call it on a const instance, i.e. double getArea() const.
You don't need the return 0; at the end, because that's the default for main. There is no such default for other functions. main is special.
In order to use cout unqualified (as it seems you want to) you can add using namespace std; at the start of the code; it's usually placed after the includes.
mutable is usually not used to allow outside code to treat part of an object as always non-const.
Instead it's used as a device to more easily let a class implementation have some non-const state also when the object appears to be const to outside code. That's called logical constness. For example, the object might cache the result of an expensive computation, even when it's const.
In C++17 and later mutable can also be applied to lambda expressions, where it yields a lambda that can change its state (captured values).

c++ class members functions: how to write these functions?

In my Object Oriented c++ course, we have to write this class that I have put below.
Point
class Point{
public:
Point( double x = 0, double y = 0 );
double getX() const;
double getY() const;
Point & setX( double x ); // mutator, returning reference to self
Point & setY( double y );
const Point & output() const;
double distance( const Point & other ) const;
private:
double xPoint, yPoint;
}; // class Point
my question is...I can't find any information on how the functions setX, setY, and output should work. They are the same type as the class itself and I have written what I would expect them to look like below. Can anyone tell me what I am doing wrong and maybe some more specifics of how these functions are working?
The setX function should change xPoint in the object, the setY should do the same for the yPoint and output should simply output them.
Point & Point::setX( double x )
{
xPoint = x;
}
Point & Point::setY( double y )
{
Ypoint = y;
}
const Point & Point::output() const
{
cout << xPoint << yPoint;
}
Just add a return *this; at the end of your setX and setY: you are returning a reference to your object, so that for example you can do: p0.setX(1.23).setY(3.45), with of course p0 an instance of Point. In the output function, put a separator between xPoint and yPoint, like a space. You say They are the same type as the class itself: don't confuse a variable type with the type returned by a function/method: the method setX, setY and output return a reference to an instance of the class to which they belong. Note that the reference returned by output is const, so you can do:
p0.setX(1.23).setY(3.45).output();
But not:
p0.output().setX(1.23);
As setX is not a const method (it doesn't declare that it won't modify the data inside the class instance to which it belongs).
You can call instead:
double x = p0.output().getX();
because getX is a const method.
Note: I am not saying you should use the methods in this way, but the point is to show what potentially you can do.
Setters are public metods thats allow you change private members of the class, they don't have return type so setX, setY should be void not Point:
void set(double x); // Declaration
void Point::setX( double x ) // Definition outside Point.h
{
xPoint = x;
}
Same with output should be void, rest is fine you can define it whatever you wish to display it, you can change it like this:
void Point::output() const
{
cout << "(" << xPoint << ", " << yPoint << ")";
}
setX() will probably change the value of the pointX member, and return a reference to the object being acted on.
So an implementation might be something like
Point &Point::setX(double xval)
{
if (IsValid(xval)) pointX = xval; // ignore invalid changes
return *this;
}
This can (assuming other member functions and operators are being used correctly) be used in things like this
#include <iostream>
// declaration of Point here
int main()
{
Point p;
std::cout << p.setX(25).setY(30).getX() << '\n';
}
While this example isn't particularly useful (it shows what is possible) the chaining of member function calls is useful in various circumstances. For example, this technique is actually the basis on which iostream insertion and extraction operators work, and allow multiple things to be inserted/extracted to/from a stream in a single statement.
The documentation of the setX and setY functions says
// mutator, returning reference to self
Your implementation does the mutation, but you've failed to complete the contract that this function is supposed to satisfy: it's supposed to return a reference to itself.
this is a pointer to the object you're invoking the method on, and so adding the line
return *this;
would complete the contract.
This is an aside, but it may help you understand why anyone would want to use such a 'strange' design.
You may be familiar with ordinary assignment being used in ways such as
a = b = 0;
if((result = some_function()) == 0) {
// Do something in the `result == 0` case
} else {
// Do something in the `result != 0` case
}
and other similar things. The first example sets both a and b to be 0. The second example stores the return value of the function call into the variable result, and then branches based on whether that value is 0 or not.
The way this works is that x = y is a binary operator that which has the side effect of copying the value of y into x, and then returns that value (technically a reference to x) so that it may be used in the surrounding expression.
So when you write a = b = 0, this is parsed as a = (b = 0), and has the effect of making b zero, and then evaluates to a = 0 which is then evaluated and makes a zero. Similarly for the branching example.
This is something people like to do when writing code (it's a completely separate topic whether or not this is good style), so when people design new types with operator= methods, they design them to support this usage, by making them return a reference to the object assigned to. e.g.
MyClass& MyClass::operator=(arg a)
{
// Copy the value of `a` into this object
return *this;
}
The other assignment operators, like operator+= also work this way.
Now, when you're used to this usage, it is a small step to extend it to other functions that sort of act like assignment, like setX and setY. This has the additional convenience of making it easy to chain modifications, as in point.setX(3).setY(7).

C++ Passing an Object to a Member Function

For a homework assignment we are asked to create two classes: a MyPoint class and a ThreeDPoint class.
Here is my MyPoint class:
#pragma once
#include <math.h>
class MyPoint
{
private:
double x, y;
public:
MyPoint()
{
x = y = 0;
}
MyPoint(double x, double y)
{
this->x = x;
this->y = y;
}
double getX()
{
return x;
}
double getY()
{
return y;
}
double distance(MyPoint pointB)
{
return sqrt((x - pointB.x) * (x - pointB.x)
+ (y - pointB.y) * (y - pointB.y));
}
};
Here is my ThreeDPoint class:
#pragma once
#include "MyPoint.h"
class ThreeDPoint : public MyPoint
{
private:
double z;
public:
ThreeDPoint() // : MyPoint()
{
z = 0;
}
ThreeDPoint(double x, double y, double z) : MyPoint(x, y)
{
this->z = z;
}
double getZ()
{
return z;
}
double distance(ThreeDPoint pointB) // function overloading
{
// x and y are private not protected
return sqrt((getX() - pointB.getX()) * (getX() - pointB.getX())
+ (getY() - pointB.getY()) * (getY() - pointB.getY())
+ (getZ() - pointB.getZ()) * (getZ() - pointB.getZ()));
}
};
And here is main:
#include <iostream>
#include "SignatureBlock.h"
#include "MyPoint.h"
#include "ThreeDPoint.h"
int main()
{
SignatureBlock myBlock;
std::cout << myBlock.toString();
MyPoint pointA(1, 2);
MyPoint pointB(4, 2.5);
std::cout << pointA.distance(pointB) << '\n';
ThreeDPoint point_a(0, 0, 0);
ThreeDPoint point_b(10, 30, 25.5);
std::cout << point_a.distance(point_b) << '\n';
return 0;
}
This code works fine. It is able to calculate the distance between two points in both 2-dimensional and 3-dimensional space. However, in the homework instructions for the ThreeDPoint class, the book says to create
"A constant get function that returns the z value"
and
"A constant distance(const MyPoint&) function to return the distance between this point and the other point in three-dimensional space."
My question is what do they mean by "A constant get function..." and "A constant distance(const MyPoint&) function..."? I understand that you can put const after a function declaration to prevent the function from changing any class members, but why is this necessary here?
Also, why would I pass const MyPoint& to the distance function rather than a ThreeDPoint object? After all we're trying to find the distance between two ThreeDPoints. I read that if you have a parent object parameter in the member function declaration any child of that parent can also be passed to the function, so maybe that has something to do with it.
Lastly, isn't the distance(const MyPoint&) in the instructions missing a name for the MyPoint& object? I did try to type this in and the compiler doesn't mind, but how would I access the members of the object being passed in?
Edit: Also, what purpose does the & serve?
Most importantly, how would I re write my code to follow exactly what the instructions state?
Thanks for reading and thank you for any suggestions anyone might have.
If you live in a world where there are no const objects, it's never necessary to mark methods const. However, it is a good idea. Using const pointers and references is a very good practice when you don't need to change members of an object, and it can help you find design flaws when your program gets bigger.
It's also a good practice to pass references to objects, because passing a reference is usually faster than passing a copy of the object. (It's also in this context that you'll use const references: it tells the caller that you want the object by reference because it's faster, not because you want to change it.)
It's legal to omit argument names, but it has the obvious consequence that you won't be able to use them in your function. It's also a common notation because compilers get rid of argument names when they create function signatures, so you'll often see error messages that look like distance(const MyPoint&) instead of distance(const MyPoint& point).
I can't help you about why they want a const MyPoint& for the ThreeDPoint class. My best guess is that they want you to assume the z component of that point is 0.