不受继承的C++保护变量

不受继承的C++保护变量,c++,class,inheritance,member,protected,C++,Class,Inheritance,Member,Protected,我已经写了一些代码来计算RSA加密算法。该程序使用类和继承,因为我想为多个用户计算公钥和私钥。有父类rsa和子类公钥和私钥 在编译下面的代码时,我遇到了许多错误。所有这些都是关于派生类在其各自的构造函数中没有可用字段的,请参见下面的错误消息代码。但是,这些变量是使用父类中的受保护访问修饰符定义的,因此子类应该可以访问它们 一个旁注:我在两个子类中都有函数键,但我认为最好在父类中放一次,对吗 代码如下: #include <iostream> #include <math.h&g

我已经写了一些代码来计算RSA加密算法。该程序使用类和继承,因为我想为多个用户计算公钥和私钥。有父类rsa和子类公钥和私钥

在编译下面的代码时,我遇到了许多错误。所有这些都是关于派生类在其各自的构造函数中没有可用字段的,请参见下面的错误消息代码。但是,这些变量是使用父类中的受保护访问修饰符定义的,因此子类应该可以访问它们

一个旁注:我在两个子类中都有函数键,但我认为最好在父类中放一次,对吗

代码如下:

#include <iostream>
#include <math.h>

using namespace std;

class rsa
{
protected:
    int p, q, d, m, n, f, e, c, end, k;

public:
    rsa() : n(0), e(0), c(0), k(0), end(0), f(0)
    { }

    void set(int , int , int, int);

    int key()
    {
        n = p * q;
        f = (p - 1) * (q - 1);

        for (k; end < 1; k++)
        {
            if ((1 + k * f) % d == 0) 
            {
                end = 2;
                e = (1 + k * f) / d;
            }
        }

        c = int(pow(m, e)) % n;

        return c;
    }
};

void rsa::set(int p_, int q_, int d_, int m_)
{
    p = p_;
    q = q_;
    d = d_;
    m = m_;
}

class public_key : public rsa
{
public:
    public_key() : n(0), e(0), c(0), k(0), end(0), f(0)
    { }
};

class private_key : public rsa
{
public:
    private_key() : n(0), e(0), c(0), k(0), end(0), f(0)
    { }
};

int main()
{
    public_key usr1, usr2;
    private_key usr1r, usr2r;

    usr1.set(11, 5, 23, 9);
    usr2.set(13, 7, 97, 6);
    usr1r.set(17, 7, 51, 8);
    usr2r.set(11, 17, 51, 4);

    cout << "Public key of user 1: " << usr1.key() << endl;
    cout << "Public key o user 2: " << usr2.key() << endl;

    cin.get();

    return 0;
}

所有其他错误都是相同的,但字段名更改。

该错误与rsa类成员的访问级别无关。即使您将这些成员声明为public,您仍然会得到错误。问题是派生类的初始化列表仅在其自身的上下文中运行,您无权访问基类成员

但是,您可以访问派生类构造函数主体中公共的或受保护的基类成员。例:

class public_key : public rsa
{
public:
    public_key()
    {
        n = 0;
        e = 0;
        c = 0;
        k = 0;
        end = 0;
        f = 0;
    }
};

class private_key : public rsa
{
public:
    private_key()
    {
        n = 0;
        e = 0;
        c = 0;
        k = 0;
        end = 0;
        f = 0;
    }
};
尽管上面的代码使用赋值而不是初始化,但它对基本类型(所有这些成员都是基本类型)执行完全相同的操作

尽管如此,尽管上面的代码是有效的,但这是做你想做的事情的错误方式。您已经为类rsa编写了构造函数,因此避免重复代码的一种方法是从初始化列表中调用现有构造函数

class public_key : public rsa
{
public:
    public_key() : rsa()
    { }
};

class private_key : public rsa
{
public:
    private_key() : rsa()
    { }
};
class public_key : public rsa
{
public:
    public_key()
    { } // rsa() will be called automatically
};

class private_key : public rsa
{
public:
    private_key()
    { } // rsa() will be called automatically
};
但是请注意,rsa是默认构造函数,因为它没有参数,因此派生类的任何构造函数都会自动调用它,除非在初始化列表中指定其他rsa构造函数

class public_key : public rsa
{
public:
    public_key() : rsa()
    { }
};

class private_key : public rsa
{
public:
    private_key() : rsa()
    { }
};
class public_key : public rsa
{
public:
    public_key()
    { } // rsa() will be called automatically
};

class private_key : public rsa
{
public:
    private_key()
    { } // rsa() will be called automatically
};
但是,既然派生类的默认构造函数为空,那么您甚至不需要它们,除非您计划添加更多逻辑

class public_key : public rsa
{
public:
    // rsa() will still be called automatically when declaring an instance of public_key
};

class private_key : public rsa
{
public:
    // rsa() will still be called automatically when declaring an instance of private_key 
};

关于key函数的旁注,如果key在两个子类中的实现相同,那么是的,在父类中只需要一次。您应该始终避免代码重复,因此即使需要为每个子类定制key的一小部分,也最好在基类中编写一个虚拟函数,key可以作为计算的一部分调用该函数。然后,在每个子类中,用任何必要的专门化重写虚函数。因此,所有的共享代码都可以保留在父类密钥函数中。

< P>根据C++标准的122.2初始化基础和成员,第2段< /P> 除非mem初始值设定项id命名构造函数的类,否则 构造函数类的非静态数据成员,或直接或 该类的虚拟基mem初始值设定项格式不正确

因此,程序中派生类的mem初始值设定项格式不正确,编译器会发出错误

应该初始化其数据成员的是基类构造函数

将类的构造函数(例如public_key)定义为

public_key () : n(0), e(0), c(0), k(0), end(0), f(0) {} ;
因为首先会调用基类的构造函数

rsa () : n(0), e(0), c(0), k(0), end(0), f(0) {};
它将初始化数据成员

所以写就足够了

rsa () {}


它应该是私钥:rsa{}

请发布准确的错误和位置。人们希望看到实际的错误消息,而不是被告知您对错误消息的解释。您不能像那样初始化基类的成员。我已编辑了问题,其中包括一个错误。我必须把所有的错误都放进去吗?@CaptainObvlious初始化有什么问题吗?编译时没有错误,但当时函数键在两个派生类中。好的,我不知道我可以在初始化列表中调用构造函数。作为参考,你能提供一个链接到你从中得到这个的部分吗?谢谢。@VladFromcow所以,无论何时创建派生类的对象,都会调用基类的构造函数,但除非在派生类的构造函数中显式指定,否则它不会初始化该对象变量!那么,如果基类的构造函数没有初始化派生类变量,除非它明确声明,为什么要调用它呢?@Mohamed Ahmed You是错的。基类的构造函数显式初始化在mem初始化器中指定的数据成员。不需要在派生类的构造函数的mem初始值设定项中指定它,因为它在任何情况下都会被调用。@Mohamed Ahmed Yes,您可以。我在我的帖子中展示了这一点。@Mohamedhamed是的,您可以简单地将派生类构造函数保留为空。事实上,如果它们是空的,就根本不需要它们。我已经更新了我的答案,包括了所有这些。你在技术上是正确的,但是你应该
d详细说明一下你的答案:-我想,但在刷新页面后,我看到了其他人的反应,所以没有必要重复。如果可以的话,我会删除我的答案。实际上,你可以在评论开始之前,点击帖子底部的链接删除你自己的答案。在这种情况下,您不需要这样做,因为您的答案在技术上是正确的,只是缺少解释。只要你的答案没有错误或误导,就没有必要删除它。