Struct对象

结构体类 Struct 是将许多属性 (atributes) 捆绑在一起的方便途径,可以使用存取器方法,而不必直接写一个类。 Struct 类是一个指定类集的生成器,它的每个子类都被定义为持有一组变量和它们的存取器。

 

也就是说, Struct.new 方法能生成 Struct 类的子类。在子类中使用 new 方法就可以生成构造体。而构造体的子类中定义了构造体成员的访问方法。

 

在下面这些例子中,我们将调用被创建的类 ”Customer” ,然后我们显示它的一个名为 joe 的实例。此外参数 symbol 引用一个符号,它即可以是个引用字符串也可以是一个 Symbol 对象,如 :name

有時候只是想要把一些資料封裝在一起, 但用到 class 實在是不太需要, 可以考慮換用 Struct 方法.
  1. Struct.new([Name,] member …), 會產生一個 “Name” 的 class
    
    NameCard = Struct.new("NameCard", :name, :age);
    puts NameCard.class
    
    
    
    
  2. 使用之前產生的 “Name” class, 你可以 new, 然後存取或寫入.
    
    a = NameCard.new("Andrew", 10)
    puts a.inspect
    
    a.age = a.age + 1;
    puts a.inspect
    
    
    
    

 

 

 

Struct 的超类是 Object ,它包含了模块 Enumerable

 

类方法:

(1) Struct.new( [aString] [, aSym]+> ) => StructClass 生成并返回一个名为 aStringStruct 类的子类,子类中定义了访问结构体成员的方法。

dog = Struct.new("Dog", :name, :age)

fred = dog.new("fred", 5)

fred.age=6

printf "name:%s age:%d", fred.name, fred.age #=>”name:fred age:6”

 

如果忽略名字 aString ,则将创建一个匿名 Struct 类的子类。否则,这个结构体的名字将作为 Struct 类内的一个常量名出现。因此,对于系统内的所有结构体来说它的名字必须是唯一的且以在写字母开头。 当首次要求无名类提供其类名时,它会搜索被赋值的常数名,若找到的话就以该常数名为类名 ( 请参考 Class.new )

例:结构体类的类名:

p Struct.new("Foo", :foo, :bar) #=> Struct::Foo

p Foo = Struct.new(:foo, :bar) #=> Foo

 

aSym 可以是 Symbol 对象或字符串。此外,若 aString 为字符串话,它会被当作类名来处理,因此可以会出现错误。所以最好使用 Symbol 来指定结构体的成员。

 

结构体类的类方法:

(1)StructClass.new(arg, ...) => obj StructClass[arg, ...] => obj Struct::new 返回一个新的 Class 对象,随后它可被用于创建指定新结构体的实例。即生成并返回结构体对象。参数将成为结构体的初始值。实际参数的数量必须小于或等于这个类定义时的属性数量;没有指定成员初始值是,成员的值被设为 nul{} 。若传递的参数多了将引起 ArgumentError 异常。

例如:

Foo = Struct.new(:foo, :bar)

foo = Foo.new(1)

p foo.values # => [1, nil]

 

再如:

# 创建有名称的 Struct 类的子类 Customer

# => Struct::Customer

Struct.new("Customer", :name, :address)

 

# 创建 Customer 结构体的实例 Dave

#=> #Main">

Struct::Customer.new("Dave", "123 Main")

 

# 使用结构体的常量名创建实例。

#=> Customer

Customer = Struct.new(:name, :address)

#=> #Main">

Customer.new("Dave", "123 Main")

 

(2) struct.members => array 以数组的形式返回结构体成员名 ( 字符串 )

例如 :

Foo = Struct.new(:foo, :bar)
       p Foo.members # => ["foo", "bar"]

 

         Customer = Struct.new( "Customer", :name, :address, :zip )

Customer.members #-> ["name", "address", "zip"]

 

实例方法:

(1) struct[symbol] => anObject struct[fixnum] => anObject 属性引用 返回名为 symbol 实例变量的值,或者由 fixnum 编写的索引 (0..length-1) 。也就是说,是返回结构体的第 nth(0..length-1) 个成员的值。若 symbol 不是 nth 而是字符串或 Symbol 对象的话,将返回同名成员的值。若指定了并不存在的成员变量,会引发 NameError 或当索引超出范围时引发 IndexError 异常。

例如:

Customer = Struct.new(:name, :address, :zip)




joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)




joe["name"]   


#=> "Joe Smith"




joe[:name]    


#=> "Joe Smith"






joe[0] 


#=> "Joe Smith"


再如:






Foo = Struct.new(:foo, :bar)


obj = Foo.new('FOO', 'BAR')


p obj[:foo] 


# => "FOO"


p obj['bar'] 


# => "BAR"


# p obj[:baz] 




# => in `[]': no member 'baz' in struct (NameError)


p obj[0] 


# => "FOO"


p obj[1] 


# => "BAR"


p obj[-1] 


# => "BAR"


# 





Array

一样,可以使用负的索引值。






p obj[2] 




# => in `[]': offset 2 too large for struct(size:2) (IndexError)

 

(2) struct[symbol] = obj => obj struct[fixnum] = obj => obj 属性赋值 symbol 指向的成员变量或 fixnum 索引的值赋 obj 值并返回它。即是,将结构体的第 nth 个成员的值设置为 obj ,并返回 obj 的值。若不是 fixnum 而是字符串或 Symbol 对象时,就将同名成员的值设为 obj 。若指定了并不存在的成员变量,会引发 NameError 或当索引超出范围时引发 IndexError 异常。

例如:

Customer = Struct.new(:name, :address, :zip)

joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)

joe["name"] = "Luke"

joe[:zip] = "90210"

joe.name #=> "Luke"

joe.zip #=> "90210"

 

(3) struct.each {|obj| block } => struct 为每个实例变量调用一次 block 块,并做为参数传递这个值。即,依次对结构体的各个成员进行迭代操作。返回 self

例如:

Customer = Struct.new(:name, :address, :zip)

joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)

joe.each {|x| puts(x) }

 

produces: Joe Smith

123 Maple, Anytown NC

12345

(4) struct.each_pair {|sym, obj| block } => struct 为每个实例变量调用一次 block 块,传递名字 (Symbol 对象 ) 和值做为参数。即,在结构体中,依次将某成员的名称 (Symbol) 和值传递给 block 块进行迭代。返回 self

例如:

Customer = Struct.new(:name, :address, :zip)

joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)

joe.each_pair {|name, value| puts("#{name} => #{value}") }

 

produces: name => Joe Smith

address => 123 Maple, Anytown NC

zip => 12345

再如:

Foo = Struct.new(:foo, :bar)

Foo.new('FOO', 'BAR').each_pair {|m, v| p [m,v]}

 

# => [:foo, "FOO"]

[:bar, "BAR"]

 

(5) struct.length => fixnum struct.size => fixnum 返回结构体的成员数量。

例如:

Customer = Struct.new(:name, :address, :zip)

joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)

joe.length #=> 3

 

(6) struct.members => array 以数组形式返回结构体的成员名 ( 字符串 )

例如:

Customer = Struct.new(:name, :address, :zip)





joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)







joe.members 


#=> ["name", "address", "zip"]





 

(7) struct.to_a => array struct.values => array 将结构体的成员的值存入数组,并返回它。

Customer = Struct.new(:name, :address, :zip)





joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)





joe.to_a[1]   


#=> "123 Maple, Anytown NC"








 

(8 ) struct.values_at(selector,... ) => an_array 以数组形式返回参数( 数值、字符串或Symbol 对象) 所指成员的值。selector 即可以是整数也可以是Range 对象。

例如:

a = %w{ a b c d e f }





a.values_at(1, 3, 5)





a.values_at(1, 3, 5, 7)





a.values_at(-1, -3, -5, -7)








a.values_at(1..3, 2...5)

<think>好的,我现在需要回答用户关于C++中初始化struct对象的问题。首先,我应该回忆C++中struct的基本概念,然后整理不同的初始化方法。用户可能需要详细的步骤和示例,所以需要结构清晰,分点说明。 首先,struct在C++中与类相似,默认成员是public的。初始化struct对象有多种方式,我需要逐一列举并解释。可能的初始化方法包括:默认初始化、成员列表初始化、构造函数初始化、C风格初始化等。 接下来,要确保每个方法都有对应的示例代码,并且用正确的LaTeX格式标注行内公式,比如变量名可能用$variable$的形式。同时,独立公式需要用$$...$$,但在这个问题中可能更多是代码示例,所以需要注意代码块的格式是否正确。 需要检查C++11之后的新特性,比如统一初始化列表(uniform initialization),是否适用。此外,聚合类(aggregate)的概念是否相关,比如当struct没有用户提供的构造函数、没有私有成员等情况,可以使用花括号初始化。 还要注意用户可能混淆C和C++中的struct初始化方式,需要指出区别。比如在C++11之前可能需要使用构造函数,而C中通常使用赋值初始化。同时,C++11引入了非静态成员初始化,可以在声明时直接给默认值。 可能遇到的问题包括:不同初始化方式的适用场景、初始化顺序、成员的默认值等。需要提醒用户注意事项,比如成员初始化的顺序要与声明顺序一致,避免依赖未初始化的成员。 最后,总结不同方法的优缺点,帮助用户根据情况选择合适的方式。确保回答结构清晰,步骤明确,示例正确,并且符合用户要求的格式,特别是正确使用LaTeX语法。</think>在C++中初始化`struct`对象有多种方式,以下是详细说明及示例: --- ### 1. **默认初始化** - 定义`struct`后直接声明对象,成员变量根据类型默认初始化(基本类型可能为未定义值) ```cpp struct Point { int x; double y; std::string name; }; Point p; // x未初始化,y未初始化,name为空字符串 ``` --- ### 2. **成员列表初始化(C++11起)** - 使用花括号`{}`直接初始化成员变量 $$\text{适用条件:struct为聚合类型(无用户自定义构造函数、无私有成员等)}$$ ```cpp Point p1 = {10, 3.14, "A"}; // C++11前 Point p2 {20, 6.28, "B"}; // C++11统一初始化 ``` --- ### 3. **构造函数初始化** - 定义构造函数显式控制初始化过程 ```cpp struct Point { int x; double y; std::string name; // 自定义构造函数 Point(int x_, double y_, const std::string& name_) : x(x_), y(y_), name(name_) {} }; Point p(30, 9.42, "C"); // 调用构造函数 ``` --- ### 4. **非静态成员初始化(C++11起)** - 在`struct`内直接为成员变量赋默认值 ```cpp struct Point { int x = 0; // 默认值 double y = 0.0; std::string name = "default"; }; Point p; // x=0, y=0.0, name="default" ``` --- ### 5. **C风格初始化(不推荐)** - 按声明顺序逐个赋值 ```cpp Point p; p.x = 50; p.y = 12.56; p.name = "D"; ``` --- ### ✨ **初始化方式对比** | 方法 | 优点 | 缺点 | |---------------------|-------------------------------|--------------------------| | 成员列表初始化 | 简洁,支持聚合类型 | 依赖成员顺序 | | 构造函数 | 灵活,可校验参数 | 需手动编写构造函数 | | 非静态成员初始化 | 提供默认值,减少未定义行为 | 无法动态设定初始值 | --- ### ⚠️ **注意事项** 1. 聚合初始化时成员顺序必须与声明一致 2. 混合使用默认值和列表初始化时,未指定的成员使用默认值 ```cpp struct Point { int x=1; double y=2.0; }; Point p {5}; // x=5, y=2.0 ``` 3. 对包含数组成员的`struct`,可用嵌套`{}`初始化 ```cpp struct Data { int arr[3]; char flags[2]; }; Data d {{1,2,3}, {'a','b'}}; ``` 选择初始化方式时,推荐优先使用**成员列表初始化**或**构造函数**以提高代码可读性和安全性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值