答:
答:
#include <iostream>
#include <string>
class Sales_data {
friend std::istream& operator>>(std::istream&, Sales_data&); // 输入
friend std::ostream& operator<<(std::ostream&, const Sales_data&); // 输出
friend Sales_data operator+(const Sales_data&, const Sales_data&); // 加法
public:
Sales_data(const std::string &s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(n*p) { }
Sales_data() : Sales_data("", 0, 0.0f) { }
Sales_data(const std::string &s) : Sales_data(s, 0, 0.0f) { }
Sales_data(std::istream &is) { is >> *this; }
Sales_data& operator+=(const Sales_data&); // 复合赋值
std::string isbn() const { return bookNo; }
private:
inline double avg_price() const {
return units_sold ? revenue / units_sold : 0;
}
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
// 输入
std::istream& operator>>(std::istream& is, Sales_data& item) {
double price = 0.0;
is >> item.bookNo >> item.units_sold >> price;
if (is) {
item.revenue = item.units_sold * price;
} else {
item = Sales_data();
}
return is;
}
// 输出
std::ostream& operator<<(std::ostream& os, const Sales_data& item) {
os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
return os;
}
// 加法
Sales_data operator+(const Sales_data& lhs, const Sales_data& rhs) {
Sales_data sum = lhs;
sum += rhs;
return sum;
}
// 复合赋值
Sales_data& Sales_data::operator+=(const Sales_data& rhs) {
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
(a) "cobble" == "stone"
(b) svec1[0] == svec2[0]
(c) svec1 == svec2
(d) "svec1[0] == "stone"
答:
(a) 内置版本
(b) string
(c) vector
(d) string
(a) %
(b) %=
(c) ++
(d) ->
(e) <<
(f) &&
(g) ==
(h) ()
答:
(a) % :取模运算符通常是对内建数值类型进行操作,但如果在类中有合适的语义,它可能是一个成员。
(b) %= :赋值运算符的扩展,通常应该是类的成员。
(c) ++ :自增运算符需要改变对象的状态,应该是类的成员。
(d) -> :箭头运算符必须是类的成员。
(e) << :这是输出流的插入运算符。通常,至少有一个操作数不是类类型(例如std::ostream),所以这应该是非成员函数。
(f) && :逻辑与运算符。如果在类中有合适的语义,它可以是成员。但通常,它应该是非成员函数。
(g) == :相等运算符通常应该是非成员函数以支持交换操作数的对称性,即a == b和b == a应该有相同的含义。
(h) () :函数调用运算符必须是类的成员。
(a) Book
(b) Date
(c) Employee
(d) Vehicle
(e) Object
(f) Tree
答:
#include <iostream>
#include <string>
class Object {
public:
// 有时需要能够创建无属性的对象,因此提供一个默认构造函数是合理的
Object() : id(counter++), name("Unnamed") {}
// 也可能想要在创建对象时就给予它一个名字,所以提供一个接受名字的构造函数也是合理的
Object(const std::string& name) : id(counter++), name(name) {}
// 获取对象的ID和名字的函数
int getId() const { return id; }
const std::string& getName() const { return name; }
// 修改对象名字的函数
void setName(const std::string& newName) { name = newName; }
private:
static int counter; // 静态成员,用于生成唯一的ID
int id; // 每个对象的唯一ID
std::string name; // 对象的名字
};
// 初始化静态成员
int Object::counter = 0;
// 输出运算符
std::ostream& operator<<(std::ostream& os, const Object& obj) {
os << "ID: " << obj.getId() << ", Name: " << obj.getName();
return os;
}
//相等运算符
bool operator==(const Object& lhs, const Object& rhs) {
return lhs.getId() == rhs.getId();
}
//不等运算符
bool operator!=(const Object& lhs, const Object& rhs) {
return !(lhs == rhs);
}
答:
// 输出
std::ostream& operator<<(std::ostream& os, const Sales_data& item) {
os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
return os;
}
答:
// 输出运算符
std::ostream& operator<<(std::ostream &os, const String &str){
os << str.begin();
return os;
}
答:
// 输出运算符
std::ostream& operator<<(std::ostream& os, const Object& obj) {
os << "ID: " << obj.getId() << ", Name: " << obj.getName();
return os;
}
答:
// 输入
std::istream& operator>>(std::istream& is, Sales_data& item) {
double price = 0.0;
is >> item.bookNo >> item.units_sold >> price;
if (is) {
item.revenue = item.units_sold * price;
} else {
item = Sales_data();
}
return is;
}
(a) 0-201-99999-9 10 24.95
(b) 10 24.95 0-210-99999-9
答:
(a) 正常执行 。
(b) 将.95读入price ,检测输入流的状态并不能防止这种输入错误。
istream& operator>>(istream& in, Sales_data& s)
{
double price; in >> s.bookNo >> s.units_sold >> price;
s.revenue = s.units_sold * price; return in;
}
答:
答:
答:
答:
答:
答:
// StrBlob
bool operator==(const StrBlob &lhs, const StrBlob &rhs) {
return lhs.data == rhs.data;
}
bool operator!=(const StrBlob &lhs, const StrBlob &rhs){
return !(lhs == rhs);
}
// StrBlobPtr
bool operator==(const StrBlobPtr &lhs, const StrBlobPtr &rhs){
auto lshSp = lhs.wptr.lock();
auto rhsSp = rhs.wptr.lock();
if (lshSp && rhsSp && lshSp == rhsSp) {
return lhs.curr == rhs.curr;
}
return false;
}
bool operator!=(const StrBlobPtr &lhs, const StrBlobPtr &rhs){
return !(lhs == rhs);
}
// StrVec
bool operator==(const StrVec &lhs, const StrVec &rhs){
return (lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()));
}
bool operator!=(const StrVec &lhs, const StrVec &rhs){
return !(lhs == rhs);
}
// String
bool operator==(const String &lhs, const String &rhs){
return (lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin()));
}
bool operator!=(const String &lhs, const String &rhs){
return !(lhs == rhs);
}
答:
bool operator==(const Object& lhs, const Object& rhs) {
return lhs.getId() == rhs.getId();
}
答:
// StrBlob
bool operator<(const StrBlob& lhs, const StrBlob& rhs) {
return std::lexicographical_compare(lhs.data->begin(), lhs.data->end(), rhs.data->begin(), rhs.data->end());
}
bool operator<=(const StrBlob& lhs, const StrBlob& rhs) {
return !(rhs < lhs);
}
bool operator>(const StrBlob& lhs, const StrBlob& rhs) {
return rhs < lhs;
}
bool operator>=(const StrBlob& lhs, const StrBlob& rhs) {
return !(lhs < rhs);
}
// StrBlobPtr
bool operator<(const StrBlobPtr& lhs, const StrBlobPtr& rhs) {
return lhs.curr < rhs.curr;
}
bool operator<=(const StrBlobPtr& lhs, const StrBlobPtr& rhs) {
return !(rhs < lhs);
}
bool operator>(const StrBlobPtr& lhs, const StrBlobPtr& rhs) {
return rhs < lhs;
}
bool operator>=(const StrBlobPtr& lhs, const StrBlobPtr& rhs) {
return !(lhs < rhs);
}
// StrVec
bool operator<(const StrVec& lhs, const StrVec& rhs) {
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
bool operator<=(const StrVec& lhs, const StrVec& rhs) {
return !(rhs < lhs);
}
bool operator>(const StrVec& lhs, const StrVec& rhs) {
return rhs < lhs;
}
bool operator>=(const StrVec& lhs, const StrVec& rhs) {
return !(lhs < rhs);
}
// String
bool operator<(const String& lhs, const String& rhs) {
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
}
bool operator<=(const String& lhs, const String& rhs) {
return !(rhs < lhs);
}
bool operator>(const String& lhs, const String& rhs) {
return rhs < lhs;
}
bool operator>=(const String& lhs, const String& rhs) {
return !(lhs < rhs);
}
答:
bool operator<(const Object& lhs, const Object& rhs) {
return lhs.getId() < rhs.getId();
}
答:
// 加法
Sales_data operator+(const Sales_data& lhs, const Sales_data& rhs) {
Sales_data sum = lhs;
sum += rhs;
return sum;
}
// 复合赋值
Sales_data& Sales_data::operator+=(const Sales_data& rhs) {
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
答:
// 加法
Sales_data& Sales_data::operator+=(const Sales_data &rhs) {
*this = *this + rhs;
return *this;
}
// 复合赋值
Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs) {
return Sales_data(lhs.isbn(), lhs.units_sold + rhs.units_sold, lhs.avg_price() + rhs.avg_price());
}
答:
Sales_data& Sales_data::operator=(const std::string &newBookNo){
bookNo = newBookNo;
return *this;
}
答:
StrVec &StrVec::operator=(initializer_list<string> il){
// alloc_n_copy 分配内存空间并从给定范围内拷贝元素
auto data = alloc_n_copy(il.begin(), il.end());
free(); // 销毁对象中的元素并释放内存空间
elements = data.first; // 更新数据成员使其指向新空间
first_free = cap = data.second;
return *this;
}
答:
// 拷贝赋值运算符
Object& Object::operator=(const Object& other) {
if (this != &other) { // 避免自赋值
name = other.name;
// 不改变id
}
return *this;
}
// 移动赋值运算符
Object& Object::operator=(Object&& other) noexcept {
if (this != &other) { // 避免自赋值
name = std::move(other.name);
// 不改变id
other.name = "Unnamed";
}
return *this;
}
答:
// 使用string 作为参数的赋值运算符,更改Object的name
Object& Object::operator=(const std::string &newName){
name = newName;
return *this;
}
答:
// StrBlob
string& StrBlob::operator[](size_t n){
check(n, "[] out of range");
return data->at(n);
}
const string& StrBlob::operator[](size_t n) const{
check(n, "[] out of range");
return data->at(n);
}
// StrBlobPtr
string& StrBlobPtr::operator[](size_t n){
auto p = check(n + curr, "[] out of range.");
return p->at(n + curr);
}
const string& StrBlobPtr::operator[](size_t n) const{
auto p = check(n + curr, "[] out of range.");
return p->at(n + curr);
}
// StrVec
std::string& StrVec::operator[](std::size_t n) { return elements[n]; }
const std::string& StrVec::operator[](std::size_t n) const { return elements[n]; }
// String
char& String::operator[](std::size_t n) { return elements[n]; }
const char& String::operator[](std::size_t n) const { return elements[n]; }
答:
StrBlobPtr& StrBlobPtr::operator++(){
// 如果 curr 已经指向了容器的尾后位置,则无法递增它
check(curr, "increment past end of StrBlobPtr");
++curr; // 将curr在当前状态下向前移动一个元素
return *this;
}
StrBlobPtr& StrBlobPtr::operator--(){
// 如果 curr 是 0,则继续递减它将产生一个无效下标
--curr; // 将curr在当前状态下向后移动一个元素
check(curr, "decrement past begin of StrBlobPtr");
return *this;
}
StrBlobPtr StrBlobPtr::operator++(int) {
// 此处无须检查有效性,调用前置递增运算时才需要检查
StrBlobPtr ret = *this; // 记录当前的值
++*this; // 向前移动一个元素,前置++需要检查递增的有效性
return ret; // 返回之前记录的状态
}
StrBlobPtr StrBlobPtr::operator--(int) {
// 此处无须检查有效性,调用前置递减运算时才需要检查
StrBlobPtr ret = *this; // 记录当前的值
--*this; // 向前移动一个元素,前置--需要检查递增的有效性
return ret; // 返回之前记录的状态
}
答:
StrBlobPtr& StrBlobPtr::operator+=(size_t n){
curr += n;
check(curr, "increment past end of StrBlobPtr");
return *this;
}
StrBlobPtr& StrBlobPtr::operator-=(size_t n){
curr -= n;
check(curr, "decrement past begin of StrBlobPtr");
return *this;
}
StrBlobPtr StrBlobPtr::operator+(size_t n) const{
StrBlobPtr ret = *this;
ret += n;
return ret;
}
StrBlobPtr StrBlobPtr::operator-(size_t n) const{
StrBlobPtr ret = *this;
ret -= n;
return ret;
}
ptrdiff_t operator-(const StrBlobPtr&lhs,const StrBlobPtr& rhs) {
auto lshSp = lhs.wptr.lock();
auto rhsSp = rhs.wptr.lock();
if (lshSp != rhsSp) {
throw std::runtime_error("Different base addresses");
}
return lhs.curr - rhs.curr;
}
答:
答:
// StrBlobPtr
std::string& StrBlobPtr::operator*() const {
auto p = check(curr, "dereference past end");
return (*p)[curr]; // (*p)是对象所指的 vector
}
std::string* StrBlobPtr::operator->() const{ // 将实际工作委托给解引用运算符
return & this->operator*();
}
// ConstStrBlobPtr
const std::string& ConstStrBlobPtr::operator*() const {
auto p = check(curr, "dereference past end");
return (*p)[curr];
}
const std::string* ConstStrBlobPtr::operator->() const{
return & this->operator*();
}
答:
答:
class Wrapper {
public:
Wrapper() = default;
Wrapper(StrBlobPtr* sbp) :pSBP(sbp) {}
//返回StrBlobPtr对象的operator->()会自动调用StrBlobPtr的operator->()
StrBlobPtr operator->() const {
return *pSBP;
}
private:
StrBlobPtr* pSBP=nullptr;
};
答:
答:
class IfThenElse {
public:
int operator()(const bool condition, const int ifTrue, const int ifFalse) const {
if (condition) {
return ifTrue;
} else {
return ifFalse;
}
}
};
答:
#include <iostream>
#include <string>
using namespace std;
class InputString {
public:
InputString(istream &input = cin) : is(input) { }
string operator()() const {
string str;
getline(is, str);
if (is) {
return str;
} else {
return "";
}
}
private:
istream &is;
};
答:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class InputString {
public:
InputString(istream &input = cin) : is(input) { }
vector<string> operator()() const {
vector<string> vec;
string str;
while (getline(is, str)) {
vec.push_back(str);
}
return vec;
}
private:
istream &is;
};
答:
#include <algorithm>
#include <iostream>
#include <vector>
class Equal {
public:
Equal(const int& v) : value(v) {}
bool operator()(const int& elem) const {
return elem == value;
}
private:
int value;
};
int main() {
std::vector<int> vec = { 1, 2, 3, 4, 3, 5, 3 };
int valueToCheck = 3;
int valueToReplaceWith = 9;
std::replace_if(vec.begin(), vec.end(), Equal(valueToCheck), valueToReplaceWith);
for (int i : vec) {
std::cout << i << " ";
}
return 0;
}
答:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
class IsLength {
public:
IsLength(int len) : length(len) {}
bool operator()(const std::string& str) const {
return str.length() == length;
}
private:
int length;
};
int main() {
std::ifstream file("example.txt");
if (!file) {
std::cerr << "Cannot open file." << std::endl;
return 1;
}
std::vector<int> counts(10, 0);
std::string word;
while (file >> word) {
for (int i = 1; i <= 10; ++i) {
if (IsLength(i)(word)) {
counts[i - 1]++;
break;
}
}
}
for (int i = 1; i <= 10; ++i) {
std::cout << "Words of length " << i << ": " << counts[i - 1] << std::endl;
}
return 0;
}
答:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
class IsLength {
public:
IsLength(int len) : length(len) {}
bool operator()(const std::string& str) const {
return length >= 10 ? str.length() >= length : str.length() == length;
}
private:
int length;
};
int main() {
std::ifstream file("example.txt");
if (!file) {
std::cerr << "Cannot open file." << std::endl;
return 1;
}
std::vector<int> counts(9, 0); // 用于存储长度1到9的单词数量
int count10plus = 0; // 用于存储长度10以上的单词数量
std::string word;
while (file >> word) {
bool counted = false;
for (int i = 1; i <= 9; ++i) {
if (IsLength(i)(word)) {
counts[i - 1]++;
counted = true;
break;
}
}
if (!counted && IsLength(10)(word)) {
count10plus++;
}
}
for (int i = 1; i <= 9; ++i) {
std::cout << "Words of length " << i << ": " << counts[i - 1] << std::endl;
}
std::cout << "Words of length 10 and above: " << count10plus << std::endl;
return 0;
}
答:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class IsShorter {
public:
bool operator()(const string& a, const string& b) const {
return a.size() < b.size();
}
};
class GE {
private:
vector<string>::size_type sz;
public:
GE(vector<string>::size_type sz) : sz(sz) {}
bool operator()(const string& a) const {
return a.size() >= sz;
}
};
class Print{
public:
void operator()(const string &s) { cout << s << " "; }
};
void elimDups(vector<string> &words){
sort(words.begin(), words.end());
auto end_unique = unique(words.begin(), words.end());
words.erase(end_unique, words.end());
}
void biggies(vector<string> &words,vector<string>::size_type sz){
elimDups(words);
stable_sort(words.begin(), words.end(),IsShorter());
auto wc = find_if(words.begin(), words.end(), GE(sz));
auto count = words.end() - wc;
cout << count << " " << (count>1? "words": "word") << " of length " << sz << " or longer" << endl;
for_each(wc, words.end(), Print());
cout << endl;
}
int main() {
vector<string> words = { "abc","abcd","abcde" };
biggies(words, 4);
return 0;
}
答:
(a)统计大于1024的值有多少个。
(b)找到第一个不等于pooh的字符串。
(c)将所有的值乘以2。
答:
(a)
auto count = std::count_if(vec.begin(), vec.end(), std::bind(std::greater<int>(), _1, 1024));
(b)
auto it = std::find_if(vec.begin(), vec.end(), std::bind(std::not_equal_to<std::string>(), _1, "pooh"));
(c)
std::transform(vec.begin(), vec.end(), vec.begin(), std::bind(std::multiplies<int>(), _1, 2));
答:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
bool isDivisibleByAll(int number, const std::vector<int>& container) {
return std::all_of(container.begin(), container.end(), [number](int divisor) {
std::modulus<int> mod;
return divisor != 0 && mod(number, divisor) == 0;
});
}
int main() {
std::vector<int> container = { 2, 3, 4 }; // 示例容器
int number = 12; // 需要检查的数字
if (isDivisibleByAll(number, container)) {
std::cout << number << " can be divided by all elements in the container." << std::endl;
} else {
std::cout << number << " cannot be divided by all elements in the container." << std::endl;
}
return 0;
}
答:
#include <iostream>
#include <string>
#include <functional>
#include <map>
using namespace std;
// 普通函数
int add(int i, int j) { return i + j; }
// lambda,其产生一个未命名的函数对象类
auto mod = [](int i, int j) { return i % j; };
// 函数对象类
struct divide {
int operator()(int denominator, int divisor) {return denominator / divisor; }
};
int main() {
map<string, function<int(int, int)>> binops = {
{ "+", add }, // 函数指针
{ "-", minus<int>() }, // 标准库函数对象
{ "/", divide() }, // 用户定义的函数对象
{ "*", [](int i, int j) { return i * j; } }, // 未命名的 lambda
{ "%", mod } }; // 命名了的lambda 对象
// 与用户交互部分
string op;
int lhs, rhs;
while (true) {
cout << "Enter an expression (for example, 3 + 4) and enter 'q' to quit: ";
cin >> lhs;
if (cin.fail()) {
break; // 非数字输入,退出循环
}
cin >> op >> rhs;
if (binops.find(op) != binops.end()) {
cout << "Result: " << binops[op](lhs, rhs) << endl;
} else {
cout << "Unknown operator: " << op << endl;
}
}
return 0;
}
答:
#include <iostream>
#include <string>
class Sales_data {
friend std::istream& operator>>(std::istream&, Sales_data&); // 输入
friend std::ostream& operator<<(std::ostream&, const Sales_data&); // 输出
friend Sales_data operator+(const Sales_data&, const Sales_data&); // 加法
public:
Sales_data(const std::string &s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(n*p) { }
Sales_data() : Sales_data("", 0, 0.0f) { }
Sales_data(const std::string &s) : Sales_data(s, 0, 0.0f) { }
Sales_data(std::istream &is) { is >> *this; }
Sales_data& operator+=(const Sales_data&); // 复合赋值
operator std::string() const { return bookNo; } // string 类型转换
explicit operator double() const { return revenue; } // double 类型转换
std::string isbn() const { return bookNo; }
private:
inline double avg_price() const {
return units_sold ? revenue / units_sold : 0;
}
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
答:
struct Integral {
operator const int();
operator int() const;
};
答:
struct Integral {
operator const int(); // 转换为 const int
operator int() const; // 转换为 int 的const类型转换运算符
};
答:
答:
class Object {
public:
// 有时需要能够创建无属性的对象,因此提供一个默认构造函数是合理的
Object() : id(counter++), name("Unnamed") {}
// 也可能想要在创建对象时就给予它一个名字,所以提供一个接受名字的构造函数也是合理的
Object(const std::string& name) : id(counter++), name(name) {}
// bool类型转换运算符
explicit operator bool() const { return name == "Unnamed" ? false : true; }
// 获取对象的ID和名字的函数
int getId() const { return id; }
const std::string& getName() const { return name; }
// 修改对象名字的函数
void setName(const std::string& newName) { name = newName; }
private:
static int counter; // 静态成员,用于生成唯一的ID
int id; // 每个对象的唯一ID
std::string name; // 对象的名字
};
// 初始化静态成员
int Object::counter = 0;
struct LongDouble {
LongDouble(double = 0.0);
operator double();
operator float();
};
LongDouble ldObj;
int ex1 = ldObj;
float ex2 = ldObj;
答:
void calc(int);
void calc(LongDouble);
double dval;
calc(dval); // 哪个 calc?
答:
struct LongDouble {
// 用于演示的成员 operator+;在通常情况下+是个非成员
LongDouble operator+(const SmallInt&);
// 其他成员与 14.9.2 节(第 521 页)一致
};
LongDouble operator+(LongDouble&, double);
SmallInt si;
LongDouble ld;
ld = si + ld;
ld = ld + si;
答:
ld = si + ld 选用了内置的加法运算符,但是ld的两个内置类型转换运算符会导致二义性。ld = ld + si 选用了LongDouble operator+(const SmallInt&)。
表达式 si + ld 的候选函数:
内置加法运算符
SmallInt operator+(const SmallInt&, const SmallInt&);
LongDouble operator+(LongDouble&, double);
表达式 si + ld 的可行函数和类型转换:
由于 C++ 不允许连续的两次用户定义的隐式转换,所以只有内置加法运算符是可行函数,使用SmallInt 和 LongDouble 各自的内置类型转换运算符分别对两个实参进行类型转换。
表达式 ld + si 的候选函数:
LongDouble operator+(const SmallInt&);
SmallInt operator+(const SmallInt&, const SmallInt&);
LongDouble operator+(LongDouble&, double);
内置加法运算符
表达式 ld + si 的可行函数和类型转换:
LongDouble operator+(const SmallInt&); 精确匹配不需要对实参进行类型转换。
LongDouble operator+(LongDouble&, double); 实参 si 需要从 SmallInt 转换为 int,然后通过 int 到 double 的标准转换实现类型转换。
内置加法运算符,使用SmallInt 和 LongDouble 各自的内置类型转换运算符分别对两个实参进行类型转换。
SmallInt s1;
double d = s1 + 3.14;
答:
SmallInt s1;
double d = s1.operator int() + 3.14;
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- ovod.cn 版权所有 湘ICP备2023023988号-4
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务