Pointer-to-Member Operators: .* and ->*

本文深入探讨了C++中指针到成员操作的使用,通过实例展示了如何利用.*和->*操作符访问类成员,包括成员函数和数据成员。详细解释了这些操作符的工作原理和限制,并提供了代码示例进行说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

expression .* expression 
expression –>* expression

The pointer-to-member operators, .* and –>*, return the value of a specific class member for the object specified on the left side of the expression. The right side must specify a member of the class. The following example shows how to use these operators:

// expre_Expressions_with_Pointer_Member_Operators.cpp
// compile with: /EHsc
#include <iostream>

using namespace std;

class Testpm {
public:
   void m_func1() { cout << "m_func1\n"; }
   int m_num;
};

// Define derived types pmfn and pmd.
// These types are pointers to members m_func1() and
// m_num, respectively.
void (Testpm::*pmfn)() = &Testpm::m_func1;
int Testpm::*pmd = &Testpm::m_num;

int main() {
   Testpm ATestpm;
   Testpm *pTestpm = new Testpm;

// Access the member function
   (ATestpm.*pmfn)();
   (pTestpm->*pmfn)();   // Parentheses required since * binds
                        // less tightly than the function call.

// Access the member data
   ATestpm.*pmd = 1;
   pTestpm->*pmd = 2;

   cout  << ATestpm.*pmd << endl
         << pTestpm->*pmd << endl;
   delete pTestpm;
}

Output

m_func1
m_func1
1
2

 

In the preceding example, a pointer to a member, pmfn, is used to invoke the member function m_func1. Another pointer to a member, pmd, is used to access the m_num member.

The binary operator .* combines its first operand, which must be an object of class type, with its second operand, which must be a pointer-to-member type.

The binary operator –>* combines its first operand, which must be a pointer to an object of class type, with its second operand, which must be a pointer-to-member type.

In an expression containing the .* operator, the first operand must be of the class type of, and be accessible to, the pointer to member specified in the second operand or of an accessible type unambiguously derived from and accessible to that class.

In an expression containing the –>* operator, the first operand must be of the type "pointer to the class type" of the type specified in the second operand, or it must be of a type unambiguously derived from that class.

Consider the following classes and program fragment:

// expre_Expressions_with_Pointer_Member_Operators2.cpp
// C2440 expected
class BaseClass {
public:
   BaseClass() // Base class constructor.
   {
   }
   void Func1()
   {
};

// Declare a pointer to member function Func1.
void (BaseClass::*pmfnFunc1)() = &BaseClass::Func1;

class Derived : public BaseClass {
public:
   Derived();  // Derived class constructor.
   void Func2();
};

// Declare a pointer to member function Func2.
void (Derived::*pmfnFunc2)() = &Derived::Func2;

int main() {
   BaseClass ABase;
   Derived ADerived;

   (ABase.*pmfnFunc1)();   // OK: defined for BaseClass.
   (ABase.*pmfnFunc2)();   // Error: cannot use base class to
                           // access pointers to members of
                           // derived classes. 

   (ADerived.*pmfnFunc1)();   // OK: Derived is unambiguously
                              // derived from BaseClass. 
   (ADerived.*pmfnFunc2)();   // OK: defined for Derived.
}
 

The result of the .* or –>* pointer-to-member operators is an object or function of the type specified in the declaration of the pointer to member. So, in the preceding example, the result of the expression ADerived.*pmfnFunc1() is a pointer to a function that returns void. This result is an l-value if the second operand is an l-value.

NoteNote

If the result of one of the pointer-to-member operators is a function, then the result can be used only as an operand to the function call operator.

<think>我们正在处理一个pip安装依赖时的错误,具体是尝试安装`matplotlib>=3.0.*`时出现的错误: 错误信息:`ERROR: Invalid requirement: 'matplotlib>=3.0.*': .* suffix can only be used with == or != operators` 这个错误的原因是:在pip的版本要求规范中,`.*`后缀只能用于`==`或`!=`操作符,不能用于`>=`等操作符。也就是说,我们不能使用`>=3.0.*`这样的写法。 正确的做法是:如果我们想要指定一个版本范围,应该使用兼容的版本指定方式。例如,我们想要安装3.0系列的任何版本(即3.0.0及以上,但低于3.1.0),我们可以写成`matplotlib>=3.0, <3.1`。 因此,解决方案是修改requirement的写法,将`matplotlib>=3.0.*`改为`matplotlib>=3.0, <3.1`。 但是,请注意,有时候我们可能希望允许3.1及以上的版本(如果它们兼容的话),那么我们就不能限制在3.0系列。所以,我们需要根据实际需求来确定版本范围。 如果我们的本意是安装3.0系列的最新版本(即3.0.x),那么使用`>=3.0, <3.1`是合适的。 如果我们的本意是安装3.0及以上版本(包括3.1、3.2等),那么我们可以直接写`matplotlib>=3.0`。 所以,具体如何修改,取决于项目对matplotlib版本的要求。 根据错误信息,我们得知当前的写法是`matplotlib>=3.0.*`,这通常表示我们想要3.0系列的任何版本(即3.0.0及以上,但不超过3.1.0)。因此,我们将其改为`matplotlib>=3.0, <3.1`。 但是,请注意,有时候项目可能使用`.*`来表示接受该系列的任何小版本,但允许下一个大版本,这实际上是不正确的。所以,我们必须根据项目的实际意图来修改。 在大多数情况下,使用`.*`是为了指定一个主版本和次版本,而允许修订版本任意。对于`>=`操作符,我们不应该使用`.*`后缀,而是应该使用不带`.*`的版本号,因为它已经隐含了允许该版本之后的任何修订版本(只要主版本和次版本相同)。但是,这里的关键是,`>=3.0`已经包括了3.0.0、3.0.1、3.0.2等,所以实际上`>=3.0`就等同于`>=3.0.0`,它会包括所有3.0.x版本,以及3.1.0、3.2.0等更高版本。 因此,如果我们只想锁定在3.0.x系列,那么必须同时指定上限`<3.1`。 总结: 1. 如果要求是3.0.x系列(即3.0.0及以上,但小于3.1.0),则改为:`matplotlib>=3.0, <3.1` 2. 如果要求是3.0及以上(包括3.1、3.2等),则改为:`matplotlib>=3.0` 但是,由于原要求是`>=3.0.*`,这通常表示第一种情况(锁定3.0.x系列),所以建议改为第一种写法。 现在,假设我们正在修改一个requirements.txt文件,或者一个setup.py中的install_requires,我们将原来的`'matplotlib>=3.0.*'`修改为`'matplotlib>=3.0, <3.1'`。 另外,我们也可以考虑使用`~=`(兼容版本)操作符。根据PEP 440,`~=`表示兼容版本,例如`matplotlib~=3.0`等价于`matplotlib>=3.0, ==3.*`,即大于等于3.0且与3.0系列兼容(也就是小于4.0)。但是,注意,这里我们原本要求的是3.0系列,而`~=3.0`实际上是允许3.0、3.1、3.2等(直到4.0之前的版本),这并不等同于3.0系列。所以,如果我们只想锁定3.0系列,应该用`~=3.0.0`,这表示`>=3.0.0, ==3.0.*`(即3.0系列的任何版本)。 因此,另一种写法是:`matplotlib~=3.0.0`。 所以,我们有两种方式: - `matplotlib>=3.0, <3.1` - `matplotlib~=3.0.0` 这两种写法是等价的。 因此,我们可以选择其中一种。 在修改后,重新运行安装命令即可。 注意:如果这个依赖要求是在一个项目中(比如requirements.txt),我们直接修改该文件即可。 如果是在安装某个包时出现的错误,那么可能是那个包的依赖声明有误,我们需要向该包的维护者报告此问题。但如果是我们自己项目中的问题,我们就修改自己的依赖声明。 根据用户提供的引用信息,并没有直接关于这个错误的引用。但是,我们根据pip的规范来解决。 步骤: 1. 找到包含错误依赖声明的地方(可能是requirements.txt,或者setup.py等)。 2. 将`matplotlib>=3.0.*`修改为`matplotlib>=3.0, <3.1`或者`matplotlib~=3.0.0`。 3. 重新运行安装命令。 如果用户是在安装某个包时,该包依赖声明有误,那么可能需要临时修改该包的依赖声明(比如fork并修改,然后从自己的fork安装),或者等待该包更新。 但根据错误信息,这个错误是在安装过程中出现的,所以很可能是用户自己指定的依赖。因此,用户应该修改自己的依赖文件。 如果用户无法修改(比如是第三方包的要求),那么可以尝试使用pip的较新版本,因为有时候pip版本较旧可能不支持某些语法。但是,这个错误提示明确指出了语法错误,所以即使更新pip,这个写法也是错误的。 因此,主要解决方案是修改依赖声明。 下面,我们生成相关问题。</think>### 错误分析 您遇到的错误 `ERROR: Invalid requirement: 'matplotlib>=3.0.*'` 是由于 **pip 版本规范语法错误**导致的。在 Python 包管理规范中: 1. `.*` 后缀**只能与 `==` 或 `!=` 运算符搭配使用**(如 `matplotlib==3.0.*`) 2. `>=`/`<=` 等运算符**禁止使用 `.*` 后缀**,这是 pip 的语法限制[^1]。 ### 解决方案 根据 [PEP 440 版本规范](https://peps.python.org/pep-0440/),请按需修改依赖声明: #### ✅ 正确写法示例 | 需求场景 | 错误写法 | 修正方案 | |---------|---------|---------| | 需要 **3.0 及以上任意版本** | `matplotlib>=3.0.*` | `matplotlib>=3.0` | | 需要 **3.0.x 系列最新版** (兼容 3.0 但不升级到 3.1) | `matplotlib>=3.0.*` | `matplotlib~=3.0.0` | | 需要 **精确的 3.0.x 系列** | `matplotlib>=3.0.*` | `matplotlib==3.0.*` | #### 🔧 操作步骤 1. **定位依赖文件** 检查以下文件中的 `matplotlib` 声明: - `requirements.txt` - `setup.py` - `pyproject.toml` - 其他包管理配置文件 2. **修改声明** 例如在 `requirements.txt` 中将: ```diff - matplotlib>=3.0.* + matplotlib>=3.0 # 或根据需求选择上述修正方案 ``` 3. **重新安装** ```bash pip install -r requirements.txt ``` ### 版本规范说明 | 运算符 | 含义 | 合法示例 | |----------|----------------------|---------------------| | `>=` | 大于等于指定版本 | `matplotlib>=3.0` | | `~=` | 兼容性版本(锁定主版本)| `matplotlib~=3.0.0` | | `== x.y.*` | 允许指定系列的补丁更新 | `matplotlib==3.0.*` | > 💡 **提示**:`~=3.0.0` 等价于 `>=3.0.0, ==3.*`,表示接受 3.0.0 以上但**不包含 4.0** 的版本[^1]。 ### 相关问题 1. 如何指定 Python 包的版本范围以避免依赖冲突? 2. `pip install` 遇到 `.* suffix can only be used with == or !=` 错误时有哪些替代方案? 3. 在 `requirements.txt` 中锁定依赖版本的最佳实践是什么? [^1]: 引用错误信息分析:`.* suffix can only be used with == or != operators` [^2]: PEP 440 版本规范标准:https://peps.python.org/pep-0440/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值