派生内部类的成员 [英] Members of derived inner classes

查看:129
本文介绍了派生内部类的成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标



我正在努力实施 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 GroupElements 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆