简体   繁体   English

C++,如何在父类中调用子方法

[英]C++, How to call a child method in the parent class

I have two classes in my project:我的项目中有两个类:

  • Style风格
  • Line线

In which, Line is the child of Style , so Line inherits from Style.其中, Line 是 Style 的子节点,所以 Line 继承自 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(子)调用 Style 类(父)的方法时,Style 的方法调用子的方法,为了更好地理解这里是代码:

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

Style.h:样式.h:

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

    protected:
        int width, height;
};

Style.cpp:样式.cpp:

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

Line.h:线.h:

#pragma once
#include "Style.h"

#include <vector>

using namespace std;

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

        vector <vector<char>> matrix;
};

Line.cpp:线.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:主要.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.显然,这段代码现在什么都不做,它只是修改了 Style 变量。

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我期望的是,当我调用 set_size() 时,除了改变变量宽度和高度的值之外,它还会改变矩阵的大小

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.我什至不知道 Line 是 Style 的孩子是否是一个好方法,无论如何,欢迎其他不包括继承的解决方案。

Thanks in advance.提前致谢。

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 .如果bFunction是在 A 中定义的虚方法,那么如果 a 实际上是B类型,则可以调用bFunction ,否则不能调用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.或者,您可以将 bFunction 声明为静态,但您将无法访问数据成员。

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();

}

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.您需要虚函数,似乎set_size应该是虚函数,但这不是唯一的方法。

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 (ie a member variable).但我质疑这是否是好的设计, Style应该是Line的一个属性(即成员变量)。 Inheritance doesn't seem appropriate here, which is why you are struggling to write the code.继承在这里似乎不合适,这就是您努力编写代码的原因。

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.我们可以在Line中重载set_size并从那里调用另一个set_size以及 draw 函数来重新创建矩阵。

This solution provides simple static polymorphism, that means a Line cannot be assigned to a Style - you probably do not need this?该解决方案提供了简单的静态多态性,这意味着不能将Line分配给Style - 您可能不需要这个? 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. draw功能中也存在错误,我在下面进行了更正。

The changes to your code are marked with a comment in the following.对您的代码所做的更改在下面标有注释。

// Line.h // 线.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 // 线.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 // 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 .可选的draw()matrix可以在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.如果需要直接调用Style的函数(set_size 除外),可以使用公共继承,但要对Style的所有构造函数(包括 default/copy/move)进行保护,这样只有Line这样的子类才能调用它们。 This would also prevent assignments of Line to Style .这也将阻止LineStyle的分配。

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM