不继承的c++保护变量

C++ Protected Variables Not Inherited

本文关键字:保护 变量 c++ 继承      更新时间:2023-10-16

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

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

旁注:我在两个子类中都有key函数,但我认为最好把它放在父类中,这是对的吗?

代码如下:

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

错误之一:

error: class ‘private_key’ does not have any field named ‘e’
   private_key () : n(0), e(0), c(0), k(0), end(0), f(0) {} ;

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

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

但是,您可以在派生类构造函数的主体中访问基类成员(publicprotected)。例:
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()
    { }
};

但是注意rsa()是默认构造函数(因为它没有参数),所以它将被派生类的任何构造函数自动调用(除非你在初始化列表中指定其他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()可以将其作为计算的一部分调用。然后,在每个子类中,用任何必要的专门化覆盖虚函数。因此,所有共享代码都可以保留在父类key()函数中。

根据c++标准(12.6.2初始化基和成员,段落#2)

除非mem-initializer-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 () = default;

应该是private_key() : rsa() {};