Home > database >  C , How to call a child method in the parent class
C , How to call a child method in the parent class

Time:07-08

I have two classes in my project:

  • Style
  • Line

In which, Line is the child of Style, so Line inherits from Style.

I need that when I call a method of the class Style (the parent) from Line (the child), the method of Style calls a method of the child, for your better understanding here is the code:

Line calls the Style function --> Style calls the Line function

Style.h:

#pragma once
class Style
{
    public:
        void set_size(int width, int height);

    protected:
        int width, height;
};

Style.cpp:

#include "Style.h"
void Style::set_size(int width, int height)
{
    Style::width = width;
    Style::height = height;
}

Line.h:

#pragma once
#include "Style.h"

#include <vector>

using namespace std;

class Line : public Style
{
    public:
        void draw();

        vector <vector<char>> matrix;
};

Line.cpp:

#include "Line.h"

void Line::draw()
{
    vector <char> row;
    int i, j;

    for (i = 0; i < Line::height; i  )
    {
        row.clear();

        for (j = 0; j < Line::height; i  )
        {
            row.push_back('-');
        }

        Line::matrix.push_back(row);
    }
}

Main.cpp:

#include <iostream>
#include "Line.h"

using namespace std;

int main()
{
    Line line;
    line.set_size(10, 10);
}

Obviously, this code for now does nothing much, it only modifies Style variables.

What I expect is that when I call set_size(), in addition to changing the value of the variables width and height, it will also change the size of the matrix

I don't know how to do what I said before.

I don't even know if it is a good method that Line is a child of Style, in any case other solutions that do not include inheritance are welcome.

Thanks in advance.

CodePudding user response:

if bFunction is a virtual method that is defined in A, then you just can call bFunction if a is actually of type B, otherwise you cannot call B::bFunction.

Here's an example.

#include <iostream>

class A
{
public:
    virtual void bFunction()
    {
        std::cout << "A::bFunction()" << std::endl;
    }

    void test()
    {
        bFunction();
    }
};

class B : public A
{
public:
    void bFunction() override
    {
        std::cout << "B::bFunction()" << std::endl;
    }
};

int main()
{
    A *a = new B(); // <- a is actually a B instance
    a->test(); // <- calls A::test that calls B::bFunction()

    delete a;
    return 0;
}

In alternative you can declare bFunction as static, but you won't be able to access data members.

CodePudding user response:

You need virtual functions, it would seem that set_size is the one that should be virtual, but this is not the only way to do it.

class Style
{
    public:
        virtual void set_size(int width, int height);
        virtual ~Style() {}
    protected:
        int width, height;
};

class Line : public Style
{
    public:
        void draw();
        virtual void set_size(int width, int height)
        {
            Style::set_size(width, height);
            ... // some code to resize matrix
        }
        vector <vector<char>> matrix;
};

But I question if this is good design, Style should be an attribute of Line (i.e. a member variable). Inheritance doesn't seem appropriate here, which is why you are struggling to write the code.

CodePudding user response:

I tried to have implementation and declaration in the same file. but you can structure it as you may feel good for your project.

#include <iostream>
#include <vector>

using namespace std;

class Line;

class Style
{
    public:
        void set_size(int width, int height){
            w = width;
            h = height;
        }

        void print(){
            cout << w << ", " << h << endl;
        }

    friend class Line;

    protected:
        int w, h;
};

class Line : public Style
{
    public:
        void draw(){
            vector <char> row;
            int i, j;

            for (i = 0; i < w; i  )
            {
                row.clear();

                for (j = 0; j < h; i  )
                {
                    row.push_back('-');
                }

                matrix.push_back(row);
            }
        }

        vector<vector<char>> matrix;
};

int main()
{
    Line line;
    line.set_size(10, 10);
    line.print();
    line.set_size(20, 20);
    line.print();

}

CodePudding user response:

We can just overload set_size within Line and call the other set_size from there and also the draw function to recreate the matrix.

This solution provides simple static polymorphism, that means a Line cannot be assigned to a Style - you probably do not need this? So the compiler always statically at compile-time knows, which class an object really is and can call the correct member function. No virtual member functions are needed.

There also were bugs in the draw function, which I corrected below.

The changes to your code are marked with a comment in the following.

// Line.h

#pragma once
#include "Style.h"

#include <vector>

using namespace std;

class Line : private Style // use private inheritance for static polymorphism
{
    public:
        void draw();
        void set_size(int width, int height); // overload set_size (override only for virtual functions)

        vector <vector<char>> matrix;
};

// Line.cpp

#include "Line.h"

void Line::set_size(int width, int height)
{
    Style::set_size(width, height); // call set_size() function of style
    draw(); // draw() to set matrix to new size
}

void Line::draw()
{
    Line::matrix.clear(); // clear matrix, if draw() is called more than once

    vector <char> row;
    int i, j;

    for (i = 0; i < Line::height; i  )
    {
        row.clear();

        for (j = 0; j < Line::width; j  ) // use Line::width and j   (there were bugs)
        {
            row.push_back('-');
        }

        Line::matrix.push_back(row);
    }
}

// Main.cpp

#include <iostream>
#include "Line.h"

using namespace std;

int main()
{
    Line line;
    line.set_size(10, 10); // calls the enhanced Line::set_size

    // The following compilation errors (when the comments are removed) are good, as they prevent wrong usage of the current class definitions
    // Style style = line; // would give error, as we have private inheritance and want to prevent 'slicing' and the calling of the wrong member functions; if a Line should be able to be assigned to a Style, you need public dynamic inheritance and virtual functions, as provided in other answers. If you do not need to assign a Line to a Style, use the simpler implementation from this answer.
    // Style* stylepointer = &line; // also would give an error
}

Optionally draw() and matrix can be made private in Line.

If you need to call functions (other than set_size) of Style directly, you can use public inheritance, but make all constructors (including default/copy/move) of Style protected, so that only children like Line can call them. This would also prevent assignments of Line to Style.

CodePudding user response:

Base function must be virtual for runtime inheritance. as follows example

class base {
public:
    virtual void print()
    {
        cout << "print base class\n";
    }
  
    void show()
    {
        cout << "show base class\n";
    }
};
  
class derived : public base {
public:
    void print()
    {
        cout << "print derived class\n";
    }
  
    void show()
    {
        cout << "show derived class\n";
    }
};
  
int main()
{
    base *bptr;
    derived d;
    bptr = &d;
  
    // Virtual function, binded at runtime
    bptr->print();
  
    // Non-virtual function, binded at compile time
    bptr->show();
    
    return 0;
}
  • Related