Moh*_*med 0 c++ inheritance class protected member
我编写了一些代码来计算RSA加密算法.该程序使用类和继承,因为我想为多个用户计算公钥和私钥.有一个父类rsa和子类public_key和private_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;
}
Run Code Online (Sandbox Code Playgroud)
其中一个错误:
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) {} ;
Run Code Online (Sandbox Code Playgroud)
所有其他错误都相同,但字段名称更改.
该错误与类成员的访问级别无关rsa.即使您声明这些成员,public您仍然会收到错误.问题是派生类的初始化列表仅在其自身的上下文中运行,您无权访问基类成员.
但是,您可以在派生类构造函数的主体中访问基类成员(即public或protected).例如:
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;
}
};
Run Code Online (Sandbox Code Playgroud)
虽然上面的代码使用了赋值而不是初始化,但是对于原始类型而言它完全相同,所有这些成员都是如此.
尽管如此,虽然上面的代码有效,但这是做错的方式.您已经为类编写了构造函数rsa,因此避免重复代码的一种方法是从初始化列表中调用现有构造函数.
class public_key : public rsa
{
public:
public_key() : rsa()
{ }
};
class private_key : public rsa
{
public:
private_key() : rsa()
{ }
};
Run Code Online (Sandbox Code Playgroud)
但是请注意,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
};
Run Code Online (Sandbox Code Playgroud)
但是现在您的派生类具有空的默认构造函数,您甚至不需要它们(除非您计划添加更多逻辑).
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
};
Run Code Online (Sandbox Code Playgroud)
关于key()函数的附注,如果key()两个子类中的实现相同,则是,在父类中只需要一次.你应该总是避免代码重复因此,即使一小部分key()需要进行自定义每个子类中,你最好写在基类,虚函数key()可以调用作为计算的一部分.然后,在每个子类中,使用任何必要的专门化覆盖虚函数.因此,所有共享代码都可以保留在父类key()函数中.
根据 C++ 标准(12.6.2 初始化基数和成员,第 #2 段)
\n\n\n\n\n除非 mem-initializer-id 命名构造函数\xe2\x80\x99s 类、构造函数\xe2\x80\x99s 类的\n 非静态数据成员、或者该类的直接或\n 虚拟基类,否则mem-initializer 格式错误。
\n
因此,程序中派生类的内存初始化器格式不正确,并且编译器会发出错误。
\n\n它是应该初始化其数据成员的基类构造函数。
\n\n定义类的构造函数没有任何意义,例如 public_key ,如下所示
\n\npublic_key () : n(0), e(0), c(0), k(0), end(0), f(0) {} ;\nRun Code Online (Sandbox Code Playgroud)\n\n因为首先会调用基类的构造函数
\n\nrsa () : n(0), e(0), c(0), k(0), end(0), f(0) {};\nRun Code Online (Sandbox Code Playgroud)\n\n它将初始化数据成员。
\n\n所以写就够了
\n\nrsa () {}\nRun Code Online (Sandbox Code Playgroud)\n\n或者
\n\nrsa () = default;\nRun Code Online (Sandbox Code Playgroud)\n