0

I have very simple code here with a Rectangle and Circle class inheriting from Shape class, and output their area and perimeter. I can't figure out why it does not compile. The error message says

error: expected identifier before ‘this’ Rectangle(float width, float height): this->width(width), this->height(height){} error expected '{' before 'this

So sth is not correct with my constructor initializer list. Before anyone suggests removal of the "this" pointer, I want to point out I'm aware the this pointer is not mandatory because the initializer can disambiguate. Removing the this pointer compilation goes fine, but I want to keep the this pointer and would like to know exactly what is the problem here.

#include <assert.h>
#include <cmath>

#define PI 3.14159

class Shape{
public:
    virtual float Area() const = 0;
    virtual float Perimeter() const = 0;
};

class Rectangle: public Shape{
public:
    Rectangle(float width, float height): this->width(width), this->height(height){}
    float Area() const{return width*height;}
    float Perimeter() const{return 2*(width+height);}
private:
    float width{0};
    float height{0};
};

class Circle: public Shape{
public:
    Circle(float radius): this->radius(radius){}
    float Area() const{return PI*radius*radius;}
    float Perimeter() const{return 2.0*PI*radius;}
private:
    float radius{0};
};

// Test in main()
int main() {
  double epsilon = 0.1; // useful for floating point equality

  // Test circle
  Circle circle(12.31);
  assert(abs(circle.Perimeter() - 77.35) < epsilon);
  assert(abs(circle.Area() - 476.06) < epsilon);

  // Test rectangle
  Rectangle rectangle(10, 6);
  assert(rectangle.Perimeter() == 32);
  assert(rectangle.Area() == 60);
}
YuZ
  • 445
  • 5
  • 18
  • 1
    Side note: Why `#define PI 3.14159` rather than [std::numbers::pi](https://en.cppreference.com/w/cpp/numeric/constants)? – Jesper Juhl Jan 31 '23 at 09:48
  • This is a good question, I think because of my lack of knowledge on every corner of the STL. – YuZ Jan 31 '23 at 09:54
  • @YuZ Even if you wasn't aware of it, you should never use macros. You could always replace it by a constant namespace variable for example. – Fareanor Jan 31 '23 at 10:19
  • What is the advantage? – YuZ Jan 31 '23 at 10:26

1 Answers1

3

Before anyone suggests removal of the "this" pointer, I want to point out I'm aware the this pointer is not mandatory

You're misunderstanding the options here. It's mandatory not to have it there. An initializer names the member you initialize. this->width isn't a name, but an expression.

Correct: Rectangle(float width, float height): width(width), height(height){}

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • Thanks for the answer. But I'm too stupid to follow. Originally I thought this pointer can't be used because the object has not yet been constructed. But I found out this is not the case. So what do you mean with "initializer names the member I initialize"? What is the difference between a name and expression? – YuZ Jan 31 '23 at 09:31
  • 2
    @YuZ: Do you have a C++ textbook? Because _name_ is a rather fundamental concept, and so is _expression_. In this example, `->` is an operator, and `this->width` is a member access expression. – MSalters Jan 31 '23 at 09:37
  • I think I understood. Does it mean usage of operators like "->" is forbidden in initializer lists? I may only put in the name of a member attribute and only written as such. Is my understanding correct? – YuZ Jan 31 '23 at 09:42
  • 2
    @YuZ: No. An initializer _list_ is a comma-separated list of _member initializers_. Each member initializer has two parts: the _name_ of the member (or base class) to initialize, and the initializer _expression_. As noted before, `this->member` is an member access expression, so it can only appear in the initializer expression part, not in the name part. – MSalters Jan 31 '23 at 09:46
  • Thanks you very much, I think I understood! It was my pleasure and an honor to be lectured by a C++ expert wiith 10 gold badges! – YuZ Jan 31 '23 at 09:51