派生内部类的成员 [英] Members of derived inner classes
问题描述
目标
我正在努力实施 IntegerRing
结构在抽象代数。这种类型的戒指是一个Abelian组(我已经实现的东西)。环配备有两个运算符+和*。
实施选择
为此,我决定定义 IntegerGroup
作为具有 GroupElement
的类具有运算符。完整的工作代码如下:
IntegerGroup.h
#ifndef DATAGROUP_H
#define DATAGROUP_H
#includeArray.h
#include< iostream>
//此组是整数mod n
//整数组中的乘法是简单的整数加法模数n
类IntegerGroup
{
public:
IntegerGroup();
IntegerGroup(int);
class GroupElement
{
int m;
IntegerGroup * group;
public:
GroupElement();
GroupElement(int,IntegerGroup *);
〜GroupElement();
GroupElement operator *(const GroupElement&);
GroupElement operator * =(const GroupElement&);
bool operator ==(const GroupElement&);
bool operator!=(const GroupElement&);
int val()const;
friend std :: ostream& operator<<<(std :: ostream& o,const GroupElement& e)
{
return(o<< e.m);
}
};
GroupElement identity()const;
int size()const;
friend std :: ostream& operator<<<(std :: ostream& o,const IntegerGroup& g)
{
return(o<< g.elements);
}
private:
int n;
// GroupElement * identity;
Array< GroupElement>元素;
void createNewElement(int);
};
#endif
IntegerGroup.cpp
#includeIntegerGroup.h
#include< new>
#include< iostream>
IntegerGroup :: IntegerGroup()
{
}
IntegerGroup :: IntegerGroup(int n)
:n (n),元素(Array< IntegerGroup :: GroupElement>(n))
{
//这是整数在[0,n-1] 0; j {
this-> createNewElement(j);
}
}
void IntegerGroup :: createNewElement(int m)
{
//创建新GroupElement
GroupElement newElement(m,这个);
//将其存储在元素中的索引m处
this-> elements [m] = newElement;
}
IntegerGroup :: GroupElement :: GroupElement()
:group(0)
{
}
b
$ b IntegerGroup :: GroupElement :: GroupElement(int m,IntegerGroup * g)
:group(g)
{
// this-> m必须在[0,g-> size() - 1]
this-> m = m%g-> size
if(this-> m< 0)this-> m = g-> size()+ this-> m;
}
IntegerGroup :: GroupElement ::〜GroupElement()
{
if(this-> group)
{
- > group = 0;
}
}
IntegerGroup :: GroupElement IntegerGroup :: identity()const
{
// IntegerGroup由[0,n -1],并且identity是0
return this-> elements [0];
}
//这个组只是整数mod n,应该是在[0,n-1]
//中填充的整数,因此乘法就是一个事在索引(a + b)返回元素%n
IntegerGroup :: GroupElement IntegerGroup :: GroupElement :: operator *(const IntegerGroup :: GroupElement& b)
{
// if该组未定义
if(!this-> group)
//我们简单地执行整数乘法
return GroupElement(this-> val()* b.val ;
//否则,执行组乘法
return GroupElement((this-> val()+ b.val())%this-> group-> size());
}
IntegerGroup :: GroupElement IntegerGroup :: GroupElement :: operator * =(const IntegerGroup :: GroupElement& b)
{
return( =(* this)* b);
}
bool IntegerGroup :: GroupElement :: operator ==(const IntegerGroup :: GroupElement& b)
{
return this-> m == bm ;
}
bool IntegerGroup :: GroupElement :: operator!=(const IntegerGroup :: GroupElement& b)
{
return!(* this == b) ;
}
int IntegerGroup :: GroupElement :: val()const {return this-> m; }
int IntegerGroup :: size()const {return this-> n; }
Array.cpp,Array.h仅仅是模板化的包装类。它的代码也已经工作。您可以找到他们的文件
原来,我的年没有使用C ++的严重OOP像这样导致我忘记的东西。首先,派生类可以访问 protected
, public
成员,而不是 private
,除非你在基类中声明派生类 friend
。
第二:如何编写复制构造函数。遗憾的是,派生类可以访问他们自己继承的 protected
数据成员,而不是基类。为了解决这个问题,我只是这样写复制构造函数:
IntegerRing :: Element :: Element(const IntegerGroup :: GroupElement: :GroupElement& el)
:IntegerGroup :: GroupElement(el)
{
}
Goal
I am working on implementing an IntegerRing
, which is a structure in abstract algebra. This type of ring is an Abelian group (something that I have already implemented) under addition. Rings are equipped with two operators, + and *.
Choice of implementation
For this reason, I have decided to define IntegerGroup
as class that has GroupElement
s that have the operators. The complete, working code for that is found below:
IntegerGroup.h
#ifndef DATAGROUP_H
#define DATAGROUP_H
#include "Array.h"
#include <iostream>
// This group is the integers mod n
// multiplication in integer group is simply integer addition modulo n
class IntegerGroup
{
public:
IntegerGroup();
IntegerGroup(int);
class GroupElement
{
int m;
IntegerGroup* group;
public:
GroupElement();
GroupElement(int, IntegerGroup*);
~GroupElement();
GroupElement operator*(const GroupElement&);
GroupElement operator*=(const GroupElement&);
bool operator==(const GroupElement&);
bool operator!=(const GroupElement&);
int val() const;
friend std::ostream& operator<<(std::ostream& o, const GroupElement& e)
{
return (o << e.m);
}
};
GroupElement identity() const;
int size() const;
friend std::ostream& operator<<(std::ostream& o, const IntegerGroup& g)
{
return (o << g.elements);
}
private:
int n;
//GroupElement * identity;
Array<GroupElement> elements;
void createNewElement(int);
};
#endif
IntegerGroup.cpp
#include "IntegerGroup.h"
#include <new>
#include <iostream>
IntegerGroup::IntegerGroup()
{
}
IntegerGroup::IntegerGroup(int n)
: n(n), elements(Array<IntegerGroup::GroupElement>(n))
{
//this is to have integers in [0,n-1]
for (int j = 0; j < n; j++)
{
this->createNewElement(j);
}
}
void IntegerGroup::createNewElement(int m)
{
// create new GroupElement
GroupElement newElement(m, this);
// store it at index m in elements
this->elements[m] = newElement;
}
IntegerGroup::GroupElement::GroupElement()
: group(0)
{
}
IntegerGroup::GroupElement::GroupElement(int m, IntegerGroup * g)
: group(g)
{
// this->m must be in [0, g->size() - 1]
this->m = m % g->size();
if (this->m < 0) this->m = g->size() + this->m;
}
IntegerGroup::GroupElement::~GroupElement()
{
if (this->group)
{
this->group = 0;
}
}
IntegerGroup::GroupElement IntegerGroup::identity() const
{
// IntegerGroup consists of all integers in [0, n-1], and identity is 0
return this->elements[0];
}
// this group is simply the integers mod n, and should be populated integers in [0,n-1]
// thus, multiplication is simply a matter of returning the element at index (a+b)%n
IntegerGroup::GroupElement IntegerGroup::GroupElement::operator*(const IntegerGroup::GroupElement& b)
{
// if the group is not defined
if (!this->group)
// we simply perform integer multiplication
return GroupElement(this->val() * b.val());
// otherwise, perform group multiplication
return GroupElement((this->val() + b.val()) % this->group->size());
}
IntegerGroup::GroupElement IntegerGroup::GroupElement::operator*=(const IntegerGroup::GroupElement& b)
{
return ((*this) = (*this) * b);
}
bool IntegerGroup::GroupElement::operator==(const IntegerGroup::GroupElement& b)
{
return this->m == b.m;
}
bool IntegerGroup::GroupElement::operator!=(const IntegerGroup::GroupElement& b)
{
return !(*this == b);
}
int IntegerGroup::GroupElement::val() const { return this->m; }
int IntegerGroup::size() const { return this->n; }
Array.cpp, Array.h are merely templated wrapper classes. The code to that is also already working. You can find the files for them on GitHub here, or you could use std::vector
instead. (It just now occurred to me that right now, I could do that.)
The problem
When I tried creating IntegerRing
, and compiling, I got a myriad of bizarre errors, most of which had to do with the class's own functions using private class data.
Here is my implementation thus far of IntegerRing
:
IntegerRing.h
#ifndef INTEGERRING_H
#define INTEGERRING_H
#include "IntegerGroup.h"
#include "Operators.h"
class IntegerRing : public IntegerGroup
{
public:
class Element : public IntegerGroup::GroupElement
{
public:
using IntegerGroup::GroupElement;
/*Element();
Element(int);
Element(int, IntegerRing*);
~Element();*/
operator IntegerGroup::GroupElement() { return IntegerGroup::GroupElement(); }
Element(const IntegerGroup::GroupElement& el)
{
// copy everything from el into *this
this->m = el.m;
this->group = el.group;
}
/*Element operator+(const Element&);
Element operator-(const Element&);
Element operator*(const Element&);
Element operator+=(const Element&);
Element operator-=(const Element&);
Element operator*=(const Element&);*/
};
Element identity(Operators);
private:
};
#endif
IntegerRing.cpp
#include "IntegerRing.h"
#include "IntegerGroup.h"
#include "Operators.h"
/*IntegerRing::Element::Element()
{
}*/
/*IntegerRing::Element(const IntegerGroup::GroupElement& el)
{
// copy everything from el into *this
this->m = el.m;
this->group = el.group;
}
/*
IntegerRing::Element IntegerRing::Element::operator+(const IntegerRing::Element& b)
{
// IntegerRing is simply Abelian group under addition
// thus, we treat the elements like group elements first, multiply under that group, and cast to ring elements
return (IntegerRing::Element)(((IntegerGroup::GroupElement)(*this)) * ((IntegerGroup::GroupElement)b));
}
IntegerRing::Element IntegerRing::Element::operator-(const IntegerRing::Element& b)
{
int val;
// if this has a group
if (this->group)
{
// compute (this->m - b.m) % this->group->size()
val = (this->m - b.m) % this->group->size();
// if that value is negative, add this->group->size() to it
if (val < 0) val = this->group->size() + val;
}
// otherwise, val is simply the integer difference of this->m,b.m
else val = this->m - b.m;
// return element with this value
return Element(val);
}
IntegerRing::Element IntegerRing::Element::operator*(const IntegerRing::Element& b)
{
if (this->group)
return IntegerRing::Element((this->m - b.m) % this->group->size());
return IntegerRing::Element(this->m - b.m);
}
IntegerRing::Element IntegerRing::Element::operator+=(const IntegerRing::Element& b)
{
return ((*this) = (*this) + b);
}
IntegerRing::Element IntegerRing::Element::operator-=(const IntegerRing::Element& b)
{
return ((*this) = (*this) - b);
}
IntegerRing::Element IntegerRing::Element::operator*=(const IntegerRing::Element& b)
{
return ((*this) = (*this) * b);
}
*/
IntegerRing::Element IntegerRing::identity(Operators op)
{
// if op is ADDITIVE
if (op == ADDITIVE)
// return what the base version of this method would return
return (IntegerRing::Element)(((IntegerGroup::GroupElement*)this)->identity());
// multiplicative identity requested, and it is 1
return (IntegerRing::Element)this->elements[0];
}
Operators.h
#ifndef OPERATORS_H
#define OPERATORS_H
enum Operators
{
ADDITIVE, MULTIPLICATIVE
};
#endif
The compiler thinks the copy constructor for IntegerRing::Element
is really a function that returns an int
.
Screenshot of errors
Here is screenshot of errors:
How do I resolve all this?
Turns out that my years of not using C++ for serious OOP like this has caused me to forget things. First of which: derived classes have access to protected
,public
members, and not private
unless you declare derived class a friend
in base class.
Second: how to write copy constructors. Sadly, derived classes have access to their own inherited protected
data members, not base class's. To remedy this, I just write copy constructor like this:
IntegerRing::Element::Element(const IntegerGroup::GroupElement::GroupElement& el)
: IntegerGroup::GroupElement(el)
{
}
这篇关于派生内部类的成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!