C++:调整基类成员在派生类中的访问属性的其他方法(同名成员和访问声明)

简介:

他方法

4.3.1 同名函数

在定义派生类的时候,C++语言允许在派生类中说明的成员与基类中的成员名字相同,也就是
说,派生类可以重新说明与基类成员同名的成员。如果在派生类中定义了与基类成员同名的
成员,则称派生类成员覆盖了基类的同名成员,在派生类中重新说明的成员。为了在派生类
中使用基类的同名成员,必须在该成员名之前加上基类名和作用域标识符“::”,即必须使
用下列格式才能访问到基类的同名函数。
基类名::成员名
下面的程序片段说明了这个要点

复制代码
class X{
 public:
   int f();
};            
class Y:public X{
 public:
   int f();
   int g();
};        
void Y::g()
{
  f();   //表示要访问的是派生类中的成员f(),即被调用的函数是Y::f() 
  X::f() //表示要访问基类中的f()
}        
对于派生类的对象的访问,也有相同的结论。例如;
Y obj;
obj.f();    //被访问的函数是Y::f()
如果要访问基类中的声明的名字,则应使用作用域标识符限定,例如;
obj.X::f(); //被访问的函数是X::f() 
复制代码

//例4.10 在派生类中定义同名成员

复制代码
#include<iostream>
#include<string>
using namespace std;
class Student{                  //声明基类Student 
  public:
     Student(int number1,string name1,float score1)   //基类的构造函数 
     {
      number = number1;
      name = name1;
      score = score1;
     }
     void print()     //在基类中定义了成员函数print 
     {
      cout<<"number:"<<number<<endl;
      cout<<"name:"<<name<<endl;
      cout<<"score:"<<score<<endl;
     }
  protected:
     int number;      //学号 
     string name;     //姓名 
     float score;     //成绩 
};
class UStudent:public Student{
  public:
     UStudent(int number1,string name1,float score1,string major1):Student(number1,name1,score1)
     {                      //定义派生类的构造函数,缀上基类的构造函数 
      major = major1;
     }
     void print()          //在派生类中重新定义了成员函数print 
     {
      Student::print();    //调用基类Student的成员函数print
      cout<<"major:"<<major<<endl; 
     }
  private:
     string major;
};
int main()
{
  //Student stu(22116,"张志",95);
  //stu.print();               //调用基类中的成员函数print 
  UStudent obj(22116,"张志",95,"信息安全");
  obj.print();                 //调用派生类中的成员函数print
  //obj.Student::print();        //调用基类中的成员函数print 
  return 0;
} 
复制代码

4.3.2 访问声明
对于公有继承,基类的公有成员函数也就是派生类的公有成员函数,这意味着外界可以用派生类
的对象调用基类的公有成员函数。但是对于私有继承,基类的公有成员函数变成了派生类的私有
成员函数。这时,外界就无法利用派生类的对象直接调用基类的成员函数,而只能通过调用派生类
的成员函数(内含调用基类成员函数的语句)间接地调用基类的成员函数。 

//例4.11 访问声明的引例

复制代码
#include<iostream>
using namespace std;
class A{                 //声明基类A 
 public:
  A(int x1)
  {
   x = x1;
  }
  void print()
  {
   cout<<"x="<<x<<endl;
  }
 private:
  int x;
}; 
class B:private A{       //声明私有派生类B 
 public:
  B(int x1,int y1):A(x1)
  {
   y = y1;
  }
  void print2()      //通过派生类B的函数print2来调用基类A的成员函数print 
  {
   //print(); 
   A::print();    
  } 
 private:
  int y;
};
int main()
{
 B b(10,20);
 b.print2();
 return 0;
}
*/
/*
运行结果是:x=10

如果将派生类中的语句
 void print2(){print()};
改写成语句
 void print2(){A::print()}; 
同时,将主函数main()中的语句
   b.print2();
改写成语句
   b.print();
程序的运行结果不会变。
*/
复制代码

 

这就是在4.3.1节中介绍过的方法。这种方法虽然执行起来比较简单,但在实际应用中却可能带来不便。有时程序员可能希望通过基类A的个别成员还能被派生类的对象直接访问,而不是通过派生类的公有成员函数间接访问。为此,C++提供了称为访问声明的特殊机制,可个别调整基类的某些成员,使之在派生类中保持原来的访问属性。访问声明的方法就是把某些基类的保护成员或公有成员直接写至派生类定义式中的同名段中,同时给基类名和作用域标识符::,利用这种方法,该成员就成为派生类的保护成员或公有成员了。

例如,把上面的基类中的print函数以A::print的形式直接写到私有派生类B中。

复制代码
class B:private A{        
 public:
  B(int x1,int y1):A(x1)
  {
   y = y1;
  }
  A::print;    //访问声明 
 private:
  int y;
}; 
这样,基类A中的print函数就调整为派生类B的公有成员函数,外界可以直接调用它了。           
---------------------------------------------------------------

//例4.12 访问声明的应用 
#include<iostream>
using namespace std;
class A{                 //声明基类A 
 public:
  A(int x1)
  {
   x = x1;
  }
  void print()
  {
   cout<<"x="<<x<<endl;
  }
 private:
  int x;
}; 
class B:private A{       //声明私有派生类B 
 public:
  B(int x1,int y1):A(x1)
  {
   y = y1;
  } 
   A::print;            //访问声明,把基类的公有成员函数print调整为私有派生类的 
                        //公有成员函数 
 private:
  int y;
};
int main()
{
 B b(10,20);
 b.print();            //调用基类的成员函数print 
 return 0;
}
复制代码

访问声明机制可以在私有派生类中个别调整从基类继承下来的成员性质,从而使外界可以通过
派生类的界面直接访问基类的某些成员,同时也不能影响其他基类成员的封闭性。
访问声明在使用时应注意以下几点。

(1)数据成员也可以使用访问声明。例如

复制代码
class A{
     private:
       ...
     public:
       int x2;
       ...  
   };   
   class B:private A{
     private:
       ...
     public:
       A::x2;    //把基类中的x2调整为派生类的公有成员 
       ...   
   };
复制代码

(2)访问声明中只含不带类型和参数的函数名或变量名。如果把上面的访问声明写成

复制代码
   void A::print;
或 
   A::print();
或
   void A::print();    
都是错误的。
复制代码

(3)访问声明不能改变成员在基类中的访问属性,也就是说,访问声明只能把原基类的保护成员调整为私有派生类中的保护成员,把原基类中的公有成员调整为调整为私有派生类中的公有成员。但是对基类的私有成员不能使用访问声明。

例如:

复制代码
 class A{
    private:
      int x3;
    public:
      int x1;
    protected:
      int x2;    
  };
  class B:private A{
    private:
       A::x3;      //错误
    protected:
       A::x1;      //错误
       A::x2;      //正确 
       A::x3;      //错误
    public:
       A::x1;      //正确
       A::x2;      //错误 
       A::x3;      //错误                    
  };
复制代码

(4)对于基类中的重载函数名,访问声明将基类中的所有同名函数起作用。这意味着对于重载函数使用访问声明是要慎重。

 

程序猿神奇的手,每时每刻,这双手都在改变着世界的交互方式!
本文转自当天真遇到现实博客园博客,原文链接:http://www.cnblogs.com/XYQ-208910/p/4912384.html ,如需转载请自行联系原作者
相关文章
|
8月前
|
API C++ Windows
Visual C++运行库、.NET Framework和DirectX运行库的作用及常见问题解决方案,涵盖MSVCP140.dll丢失、0xc000007b错误等典型故障的修复方法
本文介绍Visual C++运行库、.NET Framework和DirectX运行库的作用及常见问题解决方案,涵盖MSVCP140.dll丢失、0xc000007b错误等典型故障的修复方法,提供官方下载链接与系统修复工具使用指南。
1808 2
|
9月前
|
存储 缓存 监控
用 C++ 红黑树给公司电脑监控软件的日志快速排序的方法
本文介绍基于C++红黑树算法实现公司监控电脑软件的日志高效管理,利用其自平衡特性提升日志排序、检索与动态更新效率,并结合实际场景提出优化方向,增强系统性能与稳定性。
235 4
|
机器学习/深度学习 存储 算法
基于 C++ 布隆过滤器算法的局域网上网行为控制:URL 访问过滤的高效实现研究
本文探讨了一种基于布隆过滤器的局域网上网行为控制方法,旨在解决传统黑白名单机制在处理海量URL数据时存储与查询效率低的问题。通过C++实现URL访问过滤功能,实验表明该方法可将内存占用降至传统方案的八分之一,查询速度提升约40%,假阳性率可控。研究为优化企业网络管理提供了新思路,并提出结合机器学习、改进哈希函数及分布式协同等未来优化方向。
336 0
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
822 4
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
532 12
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
277 0
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
446 0
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)
|
设计模式 安全 C++
【C++进阶】特殊类设计 && 单例模式
通过对特殊类设计和单例模式的深入探讨,我们可以更好地设计和实现复杂的C++程序。特殊类设计提高了代码的安全性和可维护性,而单例模式则确保类的唯一实例性和全局访问性。理解并掌握这些高级设计技巧,对于提升C++编程水平至关重要。
268 16