-1

I have a parent Shape class that has a pure virtual method Area() which prints the area of a given shape and 2 child classes that inherit from this parent class, Square and Circle. Where should I include Square and Circle?

Shape.cpp

#include <string>
class Shape
{
public:
    virtual void Area() = 0;
};


class Square : public Shape
{
private:
    int height, width;
public:
    Square()
    {
        height = 5;
        width = 5;
    }
    // Inherited via Shape
    virtual void Area() override
    {
        printf("%i\n", height * width);
    }
};

class Circle : public Shape
{
private:
    int radius;
public:
    Circle()
    {
        radius = 10;
    }
    // Inherited via Shape
    virtual void Area() override
    {
        double x = pow(radius, 2);
        printf("%lf\n", 3.14 * x);
    }

};

ShapeTest.cpp

#include <iostream>
#include "Shape.cpp"

int main()
{
    Square square{};
    Circle circ{};

    square.Area();
    circ.Area();
}

My preferred option would to include them in their own separate files, something like

  • Shape.cpp
  • Square.cpp
  • Circle.cpp

but I seem to run into link issues with this, so I when I include them under the one file it works.

This would obviously get unwieldy as the number of child classes increases, so what is the correct way to do this?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
kopo222
  • 119
  • 11
  • 6
    This is very easy, and there's only one possible answer here: they must be included wherever their definitions are required. The End. – Sam Varshavchik Jul 11 '23 at 13:23
  • 2
    You should learn how header files work. Circle.hpp should include Shape.hpp, and each .cpp file should include its own .hpp – MSalters Jul 11 '23 at 13:24
  • 1
    Do you mean "include them" as in `#include`, or just where you put the definitions for organizational purposes? – Brian61354270 Jul 11 '23 at 13:24
  • As a general rule, any given `x.cpp` has an `x.hpp` or `x.h`. Any time you want to use something defined in a given `.cpp` file, you `#include` the associated header file. Like Sam says, this is not negotiable. The compiler will not guess what you're talking about. I'd split this out into seperate header files, and have functions in your `.cpp` if that's necessary. – tadman Jul 11 '23 at 13:24
  • @SamVarshavchik The question confuses terminology, it isn't asking about `#include`. It is asking about where to define derived classes, in a single large file or multiple small files. – François Andrieux Jul 11 '23 at 13:25
  • @FrançoisAndrieux: I I would have to bet, the error would be the rsult of trying to `#include` ,cpp files. But this question skipped that part of the problem and went straight to a bit subjective follow-up. – MSalters Jul 11 '23 at 13:27
  • "but I seem to run into Link issues with this, " show your code and the errors and we can help. – 463035818_is_not_an_ai Jul 11 '23 at 13:27
  • 7
    Your link problems probably stem from the fact that you are including cpp files, never do that. `#include` is for **header files only**. You pass your cpp files to the compiler (on the command line) not to each other using `#include`. – john Jul 11 '23 at 13:27
  • Actually, @MSalters, the error seems to be mostly due to writing Java code using C++ syntax. – Sam Varshavchik Jul 11 '23 at 13:27
  • *'but I seem to run into Link issues with this*' – if that's a **linker** error then you simply did not provide all your files to your compiler. You need to do `g++ shape.cpp square.cpp circle.cpp` at very least (or `clang` or whichever compiler you use). You might want to get used to using make files, cmake or any other build system or compile from within an IDE. – Aconcagua Jul 11 '23 at 13:28
  • It appears you are making the transition from single-source file projects, to multiple source and header file projects. Most C++ books ignore or gloss over this important aspect of C++ projects. **Large-Scale C++ Software Design** (1996) goes into this topic in excruciating depth (excellent book, and still topical even today, but overkill for your purposes). Carefully read the parts of your tutorial that discuss how to make header files and properly `#include` them. And how to manage a project (multiple headers & sources) in your IDE, or if you are using a **makefile**. – Eljay Jul 11 '23 at 13:34
  • Yes, nearly all of my experience with C style languages is in C# and java. I'm trying to learn C++ so many of my design patterns are coming from there, how would one structure this in C++? – kopo222 Jul 11 '23 at 13:34
  • 1
    @kopo222 - Technically the code will be formally correct if you just change `Shape.cpp` into `Shape.h`. You are *allowed* to define the classes in the header, and as long as they are about 10 lines each, that just works. With larger classes, there is a big advantage in having separate files to compile less when only one of them changes. And in a real project, each class might have a different developer, making separate files almost mandatory. – BoP Jul 11 '23 at 13:39
  • The best way to learn C++ is to completely forget everything you know about Java and C#. C++ is not Java or C#, but its syntax is similar (Java and C# copied many C++ features) but it works fundamentally differently. Assuming that because something that looks the same in C++ as it does in Java or C# it must work the same way will always end in tears. It is important to properly learn fundamental C++ concepts, from a good C++ textbook, like declarations, definitions, forward declarations, etc... Without solid grasp on basics, learning C++ will be painful. – Sam Varshavchik Jul 11 '23 at 13:45
  • Side note: `pow` for squaring variables is total overkill, just multiply the variable with itself: `printf(%f, radius * radius * 3.14);` – and if you need to fear overflow you might convert to `double` first: `printf(%f, 3.14 * radius * radius);` – Aconcagua Jul 11 '23 at 13:55
  • Generally, the ONLY places where header files that define `Square` and `Circle` need to be `#include`d are (1) code that explicitly creates instances of those classes (2) code that `#define`s any member functions OR static members of those classes or (3) code that calls member functions of `Square` or `Circle` that are specific to those classes (e.g. not inherited from `Shape`). If code only needs pointers to `Square` or `Circle` (e.g. `Square *`) but does not dereference (e.g. `some_sq->member_of_square()`) then you do NOT need to include those headers. – Peter Jul 11 '23 at 14:46

2 Answers2

2

You indeed should have separate headers and sources for each of the classes, as you desired anyway:

shape.h:

#ifndef SHAPE_H_
#define SHAPE_H_
// (include guard!)

class Shape
{
public:
    virtual void area() = 0;
};
#endif

With a class as simple as above you possibly don't need the source file, but might add further non-pure-virtual functionality, so:

shape.cpp:

#include "shape.h"

// further includes you possibly need

// possibly definition of static class variables
// (if you don't declare them inline)

// implementation of Shape's functions, if there are

square.h:

#ifndef SQUARE_H_
#define SQUARE_H_

#include "shape.h"
// or, depending on how you organize your headers:
// #include <shape.h>

class Square : public Shape
{
private:
    unsigned int height, width;
    // ^ (!) – negative with/height are pretty meaningless, aren't they?
public:
    Square()
        : height(5), width(5) // use initializer list instead!
                              // (not to be confused with std::initializer_list!)
    { }

    virtual void area() override;
};

square.cpp:

#include "square.h"
#include <cstdio> // for printf

void Square::area()
{
    printf("%u\n", height * width);
    //       ^  as I made them unsigned...
    // better: prefer iostreams (std::cout), they are safer
    // (no mismatch between format specifier and data possible)
}

Analogously for Circle...

Note, about area function, though: It should not print the value to to console, instead it should rather return the value in some appropriate format (one of the rare cases where floating point, i.e. double, actually appears suitable…).

Separating classes and IO improves re-usability tremendously (imagine you would want to re-use these classes and show the area in a GUI!).

Aconcagua
  • 24,880
  • 4
  • 34
  • 59
1

Your code should look like this:
you only need to include header files, not implementation files. and your implementation should be in cpp files not header files, so just declare the functions in the header files, and implement them in the cpp files, this way its also more readable.

EDIT:
you also need to prevent from including a header file more than once so you do this by:

  1. add this line at the top of the .h header file (if the compiler supports it):
    #pragma once
  2. else you can do it manually with this syntax:
    file.h
#ifndef FILEH
#define FILEH
// code
#endif

main.cpp

#include <iostream>
#include "Shape.h"
#include "Circle.h"
#include "Square.h"

int main()
{
    Square square{};
    Circle circ{};

    square.Area();
    circ.Area();
}

Shape.h

#pragma once
#include <string>

class Shape
{
public:
    virtual void Area() = 0;
};

Square.h

#pragma once
#include "Shape.h"

class Square : public Shape
{
private:
    int height, width;
public:
    Square()
    {
        height = 5;
        width = 5;
    }
    // Inherited via Shape
    virtual void Area() override;
};

Square.cpp

#include "Square.h"

void Square::Area()
{
    printf("%i\n", height * width);
}

Circle.h

#pragma once
#include "Shape.h"

class Circle : public Shape
{
private:
    int radius;
public:
    Circle()
    {
        radius = 10;
    }
    // Inherited via Shape
    virtual void Area() override;
};

Circle.cpp

#include "Circle.h"

void Circle::Area()
{
    double x = pow(radius, 2);
    printf("%lf\n", 3.14 * x);
}
MrDakik
  • 114
  • 6