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

时间:2014-05-11 21:35:20

标签: c++ class inheritance member protected

我编写了一些代码来计算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) {} ;

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

3 个答案:

答案 0 :(得分:5)

该错误与类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()函数中。

答案 1 :(得分:4)

根据C ++标准(12.6.2初始化基础和成员,第2段)

  

除非mem-initializer-id命名构造函数的类,否则a   构造函数类的非静态数据成员,或直接或   该类的虚拟基础,mem-initializer是不正确的。

因此,程序中派生类的mem-initializers格式错误,编译器发出错误。

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

没有任何意义来定义类的构造函数,例如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;

答案 2 :(得分:1)

应为private_key() : rsa() {};